题目:输入两个链表,找出它们的第一个公共结点。
方法一:两个单链表有公共节点,也就是说两个链表从某一个节点开始,next域都指向同一个节点,由于每个单链表节点只有一个Next域,因此从第一个公共节点开始,之后所有的节点都是重合的,不可能再出现分叉,所以,两个有公共节点而部分重合的单链表,形状看起来Y。 所以只要分别遍历两个链表到最后一个节点。如果两个尾节点是一样的,说明它们有公共节点,否则两个链表没有公共的节点。假设一个链表比另一个长K个节点,我们在长的链表上遍历K个节点,之后再同步遍历,此时我们就能保证同时到达最后一个节点。 分别遍历两个链表得到它们的长度,并求出两个长度差。在长的链表上先遍历长度之差的节点之后,再同步遍历两个链表,直到找到相同的节点。
public ListNode FindFirstCommonNode1(ListNode pHead1, ListNode pHead2) {
int len1=length(pHead1);
int len2=length(pHead2);
int dist;
ListNode langList;
ListNode shortList;
if(len1>len2)
{
langList=pHead1;
shortList=pHead2;
dist=len1-len2;
}
else {
langList=pHead2;
shortList=pHead1;
dist=len1-len2;
dist=len2-len1;
}
for(int i=0;i<dist;i++){
langList=langList.next;
}
while(langList!=null){
if(langList==shortList)
{
return langList;
}
else{
langList=langList.next;
shortList=shortList.next;
}
}
return null;
}
public int length(ListNode listNode)
{
if(listNode==null){
return 0;
}
int count=0;
while(listNode!=null)
{
++count;
listNode=listNode.next;
}
return count;
}
方法二:如果两个链表有公共结点,那么公共结点出现在两个链表的尾部。如果我们从两个链表的尾部开始向前比较,那么最后一个相同的节点就是要找的节点。在这个基础上想到了使用栈。分别把两个链表的节点放在两个栈里,这样两个链表的尾节点就位于两个栈的栈顶,接下来比较两个栈顶的时间是否相同,如果相同,则把栈顶弹出接着比较下一个栈顶,直到找到最后一个相同的节结点。
public ListNode FindFirstCommonNode2(ListNode pHead1, ListNode pHead2){
Stack<ListNode> stack1=new Stack<>();
Stack<ListNode> stack2=new Stack<>();
while(pHead1!=null){
stack1.push(pHead1);
pHead1=pHead1.next;
}
while(pHead2!=null){
stack2.push(pHead2);
pHead2=pHead2.next;
}
//peek返回栈顶的值,不会删除栈顶
ListNode Node = null;
while(!stack1.isEmpty() && !stack2.isEmpty() && stack1.peek()==stack2.peek()){
stack2.pop();
Node = stack1.pop();;
}
return Node;
}