链表对象的定义:
public static class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
快慢指针的妙用:
使用快慢指针找到中点
/*使用快慢指针找到中点
适用情况:
1.对于链表个数为奇数个时 返回中点
2.对于链表个数为偶数个时 返回中点(前一个)
*/
public static ListNode findMid1(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
/*使用快慢指针找到中点
适用情况:
1.对于链表个数为奇数个时 返回中点
2.对于链表个数为偶数个时 返回中点(后一个)
*/
public static ListNode findMid2(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
if (fast.next != null) {
slow = slow.next;
}
return slow;
}
使用快慢指针判断是否有成环问题
/*使用快慢指针判断是否有成环问题*/
public static boolean isLooped(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}
使用快慢指针来找到成环的单链表的入环点
/*使用快慢指针来找到成环的单链表的入环点*/
public static ListNode getLoppNode(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
//快慢指针一旦相遇,将快指针指向头节点
if (slow == fast) {
fast = head;
break;
}
}
//为了判断没有环的情况
if (fast.next == null || fast.next.next == null) {
return null;
}
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
找到两个不成环的单链表的交点
/*找到两个不成环的单链表的交点*/
public static ListNode getIntersectionNode1(ListNode head1, ListNode head2) {
ListNode node1 = head1;
ListNode node2 = head2;
while (node1 != node2) {
node1 = node1 == null ? head2 : node1.next;
node2 = node2 == null ? head1 : node2.next;
}
return node1;
}
找到两个成环的单链表的交点
/*找到两个成环的单链表的交点
* 有以下三种情况
* 1.两个单链表都有环但是不相交
* 2.相交点(一个)在入环点(一个)前 (和两个不成环的单链表的交点情况一样,只不过终点定为入环点)
* 3.两个入环点=两个相交点(即中间成环)*/
public static ListNode getIntersectionNode2(ListNode head1, ListNode head2, ListNode loop1, ListNode loop2) {
if (loop1 == loop2) {
//对应第二种情况
ListNode node1 = head1;
ListNode node2 = head2;
while (node1 != node2) {
node1 = node1 == loop2 ? head2 : node1.next;
node2 = node2 == loop1 ? head1 : node2.next;
}
return node1;
} else {
ListNode node1 = loop1.next;
while (node1 != loop1) {
if (node1 == loop2) {
//说明是第三种情况
return loop1;
}
node1 = node1.next;
}
//说明是第一种情况
return null;
}
}
找交点方法主体
//找交点方法
public static ListNode getIntersectionNode(ListNode head1, ListNode head2) {
if (head1 == null || head2 == null) {
return null;
}
ListNode loop1 = getLoppNode(head1);
ListNode loop2 = getLoppNode(head2);
if (loop1 == null && loop2 == null) {
return getIntersectionNode1(head1, head2);
}
if (loop1 != null && loop2 != null) {
return getIntersectionNode2(head1, head2,loop1,loop2);
}
return null;
}