// 1两个链表的第一个公共节点
public static Node findFirstCommonNode(Node head1, Node head2) {
Node tmp1 = head1;
Node tmp2 = head2;
int size1 = 0;
int size2 = 0;
while (tmp1 != null) {
tmp1 = tmp1.next;
size1++;
}
while (tmp2 != null) {
tmp2 = tmp2.next;
size2++;
}
tmp1 = head1;
tmp2 = head2;
if (size1 > size2) {
int x = size1 - size2;
while (x > 0) {
tmp1 = tmp1.next;
x--;
}
} else {
int x = size2 - size1;
while (x > 0) {
tmp2 = tmp2.next;
x--;
}
}
while (tmp1 != tmp2 && tmp1 != null && tmp2 != null) {
tmp1 = tmp1.next;
tmp2 = tmp2.next;
}
return tmp1;
}
// 2从尾到头打印链表
public ArrayList<Integer> printListFromTailToHead(Node head) {
// 递归
ArrayList<Integer> list = new ArrayList<>();
while (head != null) {
list = printListFromTailToHead(head.next);
list.add(head.data);
}
return list;
//非递归
ArrayList<Integer> list = new ArrayList<>();
Node tmp = head;
while(tmp != null) {
list.add(0,tmp.data);
tmp = tmp.next;
}
return list;
}
// 3判断链表是否有环,有环的情况下找出环的入口
public Node hasLooper(Node head) {
if (head == null || head.next == null) {
return null;
}
Node fast = head;
Node slow = head;
while (fast != null && fast.next != null) {// 无环的话,循环正常结束
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {// 有环的话,两个指针会相遇,这时退出循环
System.out.println("111");
break;
}
}
if (fast == null || fast.next == null) {// 无环的话,循环正常结束,这里判断一下
return null;
}
// 相遇之后,让其中一个指针从头开始每次一步,另外一个指针从当前位置开始,每次一步,最终这两个指针会在入口处相遇
fast = head;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
// 4删除重复节点(1-->2-->3-->3-->4-->4-->5变成1-->2-->3-->4-->5)
public Node deleteDuplicate(Node head) {
if (head == null || head.next == null) {
return head;
}
Node newHead = new Node(0);// 创建一个头节点,然后从第二个节点开始遍历
newHead.next = head;
Node pre = head;
Node last = head;
while (last != null) {// 遍历整个链表
if (last.next != null && last.data == last.next.data) {// 判断当前节点的下一个节点是否重复
while (last.next != null && last.data == last.next.data) {// 循环判断是否连续重复
last = last.next;
}
pre.next = last;// 越过重复的节点,相同的节点只保留最后一个
} else {// 没有重复,节点向后移动
pre = pre.next;
last = last.next;
}
}
return newHead.next;
}
//5链表的反转
public Node reverse(Node head) {
if(head == null || head.next == null) {
return head;
}
//递归
//先递归到最后一个节点
/*Node newHead = reverse(head.next);
//假设已经执行到最外层的递归方法了
head.next.next = head;
head.next = null;
return newHead;*/
//非递归
Node preNode = null;
Node curNode = head;
while(curNode != null) {
//先把当前节点的下一个节点记录下来,防止后续节点丢失
Node tmp = curNode.next;
//当前节点断开并反过来
curNode.next = preNode;
//preNode 与 curNode 同时向后一步
preNode = curNode;
curNode = tmp;
}
return preNode;
}
//6找到倒数第K个节点
public Node findLastK(Node head, int k) {
if (k < 0 || head == null || head.next == null) {
return null;
}
//快慢两个指针,快指针先走k步,然后两个指针再一起走
Node fast = head;
Node slow = head;
while(fast != null) {
if(k<=0) {
slow = slow.next;
}
fast = fast.next;
k--;
}
return k > 0 ? null : slow;
}
//7找到链表的中间结点
public Node findMidNode(Node head) {
if(head == null || head.next == null) {
return head;
}
Node fast = head;
Node slow = head;
while(fast !=null && fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
//8合并两个排序的链表
public Node Merge(Node list1,Node list2) {
//建立一个空链表
Node head = new Node(0);
Node tmp = head;
//同时遍历两个链表,小的节点先加入新链表
while(list1 !=null && list2!=null) {
if(list1.data<list2.data) {
tmp.next = list1;
tmp=list1;
list1 = list1.next;
}else {
tmp.next = list2;
tmp=list2;
list2 = list2.next;
}
}
//最后把没遍历完的链表全部加入新链表
if(list1 != null) {
tmp.next = list1;
}
if(list2 != null) {
tmp.next = list2;
}
//返回值应该是新链表的第二个节点开始
return head.next;
}
链表的基本操作
最新推荐文章于 2022-08-29 14:49:54 发布