剑指Offer(Java版):两个链表的第一个公共结点

题目:输入两个链表,找出它们的第一个公共结点。面试

面试的时候碰到这道题,不少应聘者的第一反应就是蛮力法:在第一链表 上顺序遍历每一个结点,没遍历到一个结点的时候,在第二个链表上顺序遍历每一个结点。若是在第二个链表上有一个结点和第一个链表上的结点同样,说明两个链表在 这个结点上重合,因而就找到了他们的公共结点。若是第一个链表的长度为m,第二个链表的长度为n,显然该方法的时间复杂度为O(mn).get

一般蛮力法不会是最好的办法,咱们接下来试着分析有公共结点的两个链 表有哪些特色。从链表结点的定义能够看出,这两个链表是单链表。若是两个单向链表有公共的结点,那么这两个链表从某一结点开始,它们的m_pNext都指 向同一个结点,但因为是单向链表的结点,以后他们全部结点都是重合的,不可能再出现分叉。因此两个有公共结点而部分重合的链表,拓扑形状开起来像一个Y, 而不可能项X。class

通过分析咱们发现,若是两个链表有公共结点,那么公共结点出如今两个 链表的尾部。若是咱们从两个链表的尾部开始往前比较,最后一个相同的结点就是咱们要找的结点。可问题是在单向链表中,咱们只能从头结点开始按顺序遍历,最 后才能到达尾节点。最后到达的尾节点却要最早被比较,这听起来是否是像后进先出,也是咱们就能想到用栈的特色来解决这个问题:分别把两个链表的结点放入两 个栈里,这样两个链表的尾节点就位于两个栈的栈顶,接下来比较两个栈顶的结点是否相同。若是相同,则把栈顶弹出接着比较下一个栈顶,直到找到最后一个相同 的结点。test

在上述思路中,咱们须要用两个辅助栈。若是链表的长度分别为m和n,那么空间复杂度是O(m+n)。这种思路的时间复杂度也是O(m+n).和最开始的蛮力法相比,时间效率获得了提升,至关因而用空间消耗换取了时间效率。效率

之因此须要用到栈,是由于咱们想同时遍历到达两个栈的尾节点。当两个 链表的长度不相同时,若是咱们从头开始遍历到达两个栈的尾节点的时间就不一致。其实解决这个问题还有一个更简单的办法:首先遍历两个链表获得他们的长度, 就能知道哪一个链表比较长,以及长的链表比短的链表多几个结点。在第二次遍历的时候,在较长的链表上先走若干步,接着再同时在两个链表上遍历,找到第一个相 同的结点就是他们的第一个公共结点。List

第三种思路比第二种思路相比,时间复杂度为O(m+n),但咱们不在须要辅助栈,所以提升了空间效率。当面试官确定了咱们的最后一个思路的时候,能够动手写代码了。遍历

Java代码实现:方法

package cglib;im

class ListNode{
    int data;
    
    ListNode nextNode;
    
}链表

public class jiekou {

    
        public static void main(String[] args) {
        ListNode head1=new ListNode();
        ListNode second1=new ListNode();
        ListNode third1=new ListNode();
        ListNode forth1=new ListNode();
        ListNode fifth1=new ListNode();
        ListNode head2=new ListNode();
        ListNode second2=new ListNode();
        ListNode third2=new ListNode();
        ListNode forth2=new ListNode();
        head1.nextNode=second1;
        second1.nextNode=third1;
        third1.nextNode=forth1;
        forth1.nextNode=fifth1;
        head2.nextNode=second2;
        second2.nextNode=forth1;
        third2.nextNode=fifth1;
        head1.data=1;
        second1.data=2;
        third1.data=3;
        forth1.data=6;
        fifth1.data=7;
        head2.data=4;
        second2.data=5;
        third2.data=6;
        forth2.data=7;
        jiekou test=new jiekou();
        System.out.println(test.findFirstCommonNode(head1, head2).data);
        }
        public ListNode findFirstCommonNode(ListNode head1,ListNode head2){
        int len1=getListLength(head1);
        int len2=getListLength(head2);
        ListNode longListNode=null;
        ListNode shortListNode=null;
        int dif=0;
        if(len1>len2){
        longListNode=head1;
        shortListNode=head2;
        dif=len1-len2;
        }else{
        longListNode=head2;
        shortListNode=head1;
        dif=len2-len1;
        }
        for(int i=0;i<dif;i++){ longListNode=longListNode.nextNode;
        }
        while(longListNode!=null&&shortListNode!=null
        &&longListNode!=shortListNode){ longListNode=longListNode.nextNode; shortListNode=shortListNode.nextNode;
        }
        return longListNode;
        }
        private int getListLength(ListNode head1) {
        int result=0;
        if(head1==null)
        return result;
        ListNode point=head1;
        while(point!=null){
        point=point.nextNode;
        result++;
        }
        return result;
        }

    }
   

输出:6

相关文章
相关标签/搜索