问题描述
如图所示,两个链表A和B,头节点已知,存在公共子节点c1,c1的位置和数量是不确定的,要求找到A,B的第一个公共子节点。详见leetcode
方法一 基于哈希和集合实现
方法描述
将其中一个链表存储在哈希或者集合中,遍历另一个链表,判断当前遍历结点是否存在于哈希或者集合中,如存在,即是第一个公共子结点,如遍历结束,仍未找到,则不存在公共子节点
代码实现
public static LinkedNode getIntersectionNode(LinkedNode headA, LinkedNode headB){
HashSet<LinkedNode> hashSet = new HashSet<LinkedNode>();
while (headA!=null){
hashSet.add(headA);
headA = headA.next;
}
while (headB!=null){
if (hashSet.contains(headB)){
return headB;
}
headB = headB.next;
}
return null;
}
方法二 基于栈实现
方法描述
将两个链表分别压入两个栈中,之后将栈中元素依次出栈,比较是否相同,如相同,记录当前元素,继续遍历,直至不相同之前的最后一个相同元素就是公共子节点,如第一次出栈比较就不相同,说明没有公共子节点
代码实现
public static LinkedNode getIntersectionNode(LinkedNode headA, LinkedNode headB){
Stack<LinkedNode> stackA = new Stack();
Stack<LinkedNode> stackB = new Stack();
while (headA!=null){
stackA.push(headA);
headA = headA.next;
}
while (headB!=null){
stackB.push(headB);
headB = headB.next;
}
LinkedNode intersectionNode = null;
while (stackA.size()>0&& stackB.size()>0){
if(stackA.peek() == stackB.peek()){
intersectionNode = stackA.pop();
stackB.pop();
}
else {
break;
}
}
return intersectionNode;
}
方法三 基于拼接字符串实现
方法描述
以上图的A、B链表为例
A:a1、a2、c1、c2、c3
B:b1、b2、b3、c1、c2、c3
可以在A之后拼接B,B之后拼接A,
AB:a1、a2、c1、c2、c3、b1、b2、b3、c1、c2、c3
BA:b1、b2、b3、c1、c2、c3、a1、a2、c1、c2、c3
此时可以发现 A与B的第一个公共子节点一定存在于AB、BA自后向前的最后一个相同节点,C1
实际操作过程中的拼接使用指针指向另一个链表即可
代码实现
public static LinkedNode getIntersectionNode(LinkedNode headA, LinkedNode headB){
LinkedNode iterA = headA;
LinkedNode iterB = headB;
if (headA==null||headB==null){
return null;
}
while(iterA != iterB){
iterA = iterA.next;
iterB = iterB.next;
if (iterA == null){
iterA = headB;
}
if (iterB == null){
iterB = headA;
}
}
return iterA;
}
方法四 基于差和双指针实现
方法描述
假设A的长度为La,B的长度为Lb,差为|La-Lb|,可以遍历长的链表指针先遍历|La-Lb|,之后两个指针一起遍历,遍历到的第一个相同节点即为第一个公共子节点
代码实现
public static LinkedNode getIntersectionNode4(LinkedNode headA, LinkedNode headB) {
LinkedNode iterA = headA;
LinkedNode iterB = headB;
int la = 0;
int lb = 0;
while (iterA != null) {
la++;
iterA = iterA.next;
}
while (iterB != null) {
lb++;
iterB = iterB.next;
}
int l = la > lb ? la - lb : lb - la;
iterA = headA;
iterB = headB;
if (la > lb) {
for (int i = 0; i < l; i++) {
iterA = iterA.next;
}
}
if (la < lb) {
for (int i = 0; i < l; i++) {
iterB = iterB.next;
}
}
while (iterA!=null&&iterB!=null) {
if (iterA == iterB){
return iterA;
}
iterA = iterA.next;
iterB = iterB.next;
}
return null;
}