白银挑战:链表的高频面试算法题
1.剑指 Offer 52. 两个链表的第一个公共节点
解法一:双指针差值; 遍历两个链表记录每个链表的长度;计算两个链表长度的差值;让长链表先走差值步;然后长,短链表一起走,直到碰到第一个相交位置;
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0;
int lenB = 0;
ListNode curA = headA;
ListNode curB = headB;
while (curA != null) {
lenA++;
curA = curA.next;
}
while (curB != null) {
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
int len = 0;
if (lenA > lenB) {
len = lenA - lenB;
while (len > 0) {
curA = curA.next;
len--;
}
} else {
len = lenB - lenA;
while (len > 0) {
curB = curB.next;
len--;
}
}
ListNode res=null;
while (curA != null && curB != null) {
if(curA==curB){
res=curA;
break;
}
curA = curA.next;
curB = curB.next;
}
return res;
}
}
解法二:双指针; 假设两个链表的公共长度为 c ,链表1的总长度为 a, 链表2的总长度为 b;
指针left 先遍历完 headA链表,再开始遍历headB; 指针right 先遍历完B链表,再开始遍历headA,那么left 和 right 指针一定会在第一个公共节点相遇 (前提是 headA 和 headB 能相交);
为什么会相遇在第一个公共节点处?
left 先走完 headA,长度为 a ; 再遍历 headB,走到第一个公共节点处,长度为b-c; left总共走过的路程为 a+b-c;
right先走完headB,长度为b ; 再遍历 headA, 走到第一个公共节点处,长度为a-c;right总共走过的路程为b+a-c;
left 和 right 走过的路程相等;所以left,right 一定会在 第一个公共节点处相遇;
public static ListNode otherMethod(ListNode headA, ListNode headB) {
ListNode left = headA;
ListNode right = headB;
ListNode res=null;
// 循环结束的条件有两种,一种是left == null && right==null; 也就是left,right指针同时为null;这种情况只有在两个链表不相交的情况下才会出现
// 另一种是找到了第一个公共的节点
while (left !=null || right !=null) {
if(left == right){
res=left;
break;
}
left = left != null ? left.next : headB;
right = right != null ? right.next : headA;
}
return res;
}