当我写本题的时候脑子里是有模拟法的思维的,但是当我看到Leecode的K神的双指针解法的时候瞬间感受到了一道算法题解程序可以多么简洁多么牛逼,话不多说,进入正题,这道题最大的意义在于双指针法的应用以及结合题目的数学思维模拟
例02.07题目:
1.结合数学思维的双指针法(共两种解法)
(1)利用长度差
设两个指针分别指向两个链表的头结点,对两个链表进行遍历得到他们的长度,长度差设为gap,将长的一个链表的指针往后走gap步。接着让两个指针同时往后走,比较两个指针所指节点是否相同若相同则可以判断是相交节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null){
return null;
}
int lenA=0,lenB=0;
ListNode a=headA;
ListNode b=headB;
//创建双指针
while(a.next!=null){
lenA ++;
a=a.next;
}
a=headA;
while(b.next!=null){
lenB++;
b=b.next;
}
//计算两个链表的长度
b=headB;
int steps=(lenA>lenB)? lenA-lenB:lenB-lenA;
//利用三目运算符计算长度差值
if(lenA>lenB){
while(steps>0){
a=a.next;
steps--;
}
}else if(lenB>lenA){
while(steps>0){
b=b.next;
steps--;
}
}
//将长的链表的指针往后走steps步
while(a!=b){
a=a.next;
b=b.next;
}
//判断两个指针的节点是否相同若相同则找到公共链表的第一个节点
return a;
}
}
(2)构造循环让双指针相遇
这个方法非常的巧妙,假设链表A的长度为a,链表b的长度为b,公共链表的长度为c,则非公共链表的长度分别为a-c,b-c,让他们分别加上b和a则可以构造a+b-c=a+b-c,这样便可以想到链表A的指针遍历完链表A再从链表B开始遍历(此时链表B的指针也这么操作)直到两个指针相同
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA, B = headB;
//构造双指针
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next : headA;
}
//利用数学思维构造的循环判断(a+b-c=b+a-c)
//当A=B的时候只有两种情况
//(1)A,B没有相交节点,此时A=B=NULL
//(2)A=B=相交链表的第一个节点
return A;
}
}