算法通关村第一关——链表经典问题之两个链表的第一个公共子节点
leetcode 160 题
解决思路
Set 或 Map 集合
先遍历其中一个链表,将所有节点存入 Set 集合中,在遍历另一个链表查看 set 中有无当前的节点,如果有就说明是当前节点是公共子节点
private ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet<>();
while (headA != null) {
set.add(headA);
headA = headA.next;
}
while (headB != null) {
if (set.contains(headB))
return headB;
headB = headB.next;
}
return null;
}
使用栈
- 先将 a 链表遍历存到 stackA 栈中
- 将 b 链表遍历存到 stackB 栈中
- 遍历两个栈同时出栈,直到遇到出栈节点不同的,遇到不同的节点说明从当前节点往后是公共子节点
private ListNode byStack(ListNode headA, ListNode headB) {
Stack<ListNode> stackA = new Stack<>();
Stack<ListNode> stackB = new Stack<>();
while (headA != null) {
stackA.add(headA);
headA = headA.next;
}
while (headB != null) {
stackB.add(headB);
headB = headB.next;
}
ListNode resNode = null;
while (stackA.size() > 0 && stackB.size() > 0) {
if (stackA.peek() != stackB.peek()) {
break;
}
resNode = stackA.pop();
stackB.pop();
}
return resNode;
}
差和双指针
思想:
先计算两个链表的长度 lenA,lenB,然后将长的一个链表的头结点向前移动 lenA-lenB个位置;
两个链表从 head 到尾节点长度相同时,遍历两个链表校验节点是否相等,如果相等说明是公共子节点;
private ListNode byLength(ListNode headA, ListNode headB) {
int lenA = 0,lenB = 0;
ListNode curA = headA,curB = headB;
while(curA != null) {
lenA++;
curA = curA.next;
}
while(curB != null) {
lenB++;
curB = curB.next;
}
while (lenA > lenB) {
headA = headA.next;
lenB++; // or lenA--;
}
while (lenA < lenB) {
headB = headB.next;
lenA++; // or lenB--;
}
while(headA != null && headB != null) {
if (headA == headB) return headA;
headA = headA.next;
headB = headB.next;
}
return null;
}
假如公共子节点一定存在第一轮遍历,假设La长度为L1,Lb长度为L2.则|L2-L1|就是两个的差值。第二轮遍历,长的先走|L2-L1|,然后两个链表同时向前走,结点一样的时候就是公共结点了。
拼接两个链表
先看下面的链表A和B:
A: 0-1-2-3-4-5
B: a-b-4-5
如果分别拼接成AB和BA会怎么样呢?
AB:0-1-2-3-4-5-a-b-4-5
BA:a-b-4-5-0-1-2-3-4-5
由此可以得出在拼接两个链表之后,同时遍历链表找到节点相同的就是公共结点了;
拼接有两方式:
- 物理拼接:一开始就新建两个拼接好的新链表,但是会比较废空间
- 逻辑拼接:不拼接,如果某个节点遍历完了就把该节点指向另一个链表的表头既可
private ListNode byIter(ListNode headA, ListNode headB) {
ListNode a = headA, b = headB;
while(a != b) {
if (a == null || b == null) {
return null;
}
a = a.next;
b = b.next;
if (a != b) {
if (a == null) a = headB;
if (b == null) b = headA;
}
}
return a;
}