剑指offer——两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
解:刚开始看这道题的时候,想的很简单,就是两个一起遍历,然后找到一样个一样的值就返回就行了,后来一直不通过,就很郁闷。
然后看了解析,说的是第一个公共结点的意思其实是从这一个公共结点之后的结点一直都是一样的。直到链表的末尾。
所以可以从链表的尾部开始查找,直到没有相同的结点的前一个结点就是他们的公共结点。
但是链表只能单向查找,所以要想从后往前查找的话,用栈比较方便(先入后出),将两个链表依次入栈,然后从两个栈的栈顶依次出栈,碰到不同的结点的前一个结点就是所求,即要记录出栈的那个结点
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }*/ import java.util.Stack; public class Solution { public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { if(pHead1 == null && pHead2 == null) return null; ListNode node1 = pHead1, node2 = pHead2; Stack<ListNode> stack1 = new Stack<>(); Stack<ListNode> stack2 = new Stack<>(); while(node1 != null){ stack1.push(node1); node1 = node1.next; } while(node2 != null){ stack2.push(node2); node2 = node2.next; } int len1 = stack1.size(); int len2 = stack2.size(); ListNode node = null; while(!stack1.empty() && !stack2.empty()){ if(stack1.peek() == stack2.peek()) { node = stack1.peek(); } else{ break; } stack1.pop(); stack2.pop(); } return node; } }
还有一种方法:相同的部分,肯定是从后向前(到最后一个结点都相等才行),
求两个链表的长度,的,长链表长的那一部分先走完,然后对于相等的部分, 再一起走,直到找到第一个公共结点。
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }*/ public class Solution { public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { if(pHead1 == null || pHead2 == null) return null; ListNode node1 = pHead1, node2 = pHead2; int len1 = 0, len2 = 0; while(node1 != null){ len1++; node1 = node1.next; } while(node2 != null){ len2++; node2 = node2.next; } node1 = len1 > len2 ? pHead1 : pHead2; node2 = len1 < len2 ? pHead1 : pHead2; int sub = Math.abs(len1 - len2); while(sub > 0){ sub--; node1 = node1.next; } while(node1 != node2){ node1 = node1.next; node2 = node2.next; } return node1; } }