剑指Offer-链表-面试题52:两个链表的第一个公共结点


输入两个链表,找出它们的第一个公共结点。

思路

(1)此处公共结点指的是同一个结点,而不是结点的值相同,意味着两个链表会相交。
(2)第一种思路为暴力解法,在链表1中每遇到一个结点时,遍历另外一个链表。时间复杂度为O(mn)。
(3)第二种思路为从后向前遍历,但是本题是单向链表,故借助栈的特性。时间复杂度降为O(m+n),同时需要空间复杂度O(m+n)。
(4)第三种思路先计数出两个链表的长度差值,然后利用引用相同的特性进行判断。

解法1-暴力

nowcoder的AC
提交时间:2020-01-06 ,语言:Java ,运行时间: 22 ms ,占用内存:9692K ,状态:答案正确

/*
public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode node1 = pHead1;
        ListNode node2 = pHead2;
         
        if(pHead1==null || pHead2==null){
            return null;
        }
         
        while(node1!=null){
            node2=pHead2;
            while(node2!=null){
                if(node1==node2){
                    return node1;
                }
                node2=node2.next;
            }
            node1=node1.next;
        }
        return null;
    }
}

解法2-栈

(1)注意栈的类型也是可以用ListNode,不仅仅是Integer。Stack<ListNode> stack1=new Stack<>();,然后再栈中就可以存放引用了。
(2)if判断条件里面不要进行变量的操作,否则会乱掉。先把值取出来,再直接比较值。
nowcoder的AC
提交时间:2020-01-06 ,语言:Java ,运行时间: 22 ms ,占用内存:9664K ,状态:答案正确

/*
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) {
        ListNode node1 = pHead1;
        ListNode node2 = pHead2;
         
        if(pHead1==null || pHead2==null){
            return null;
        }
         
        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;
        }
         
        ListNode pop1=null;
        ListNode pop2=null;
        
        while(stack1.size()!=0 && stack2.size()!=0){
             pop1=stack1.pop();
             pop2=stack2.pop();
             
            if(pop1!=pop2){
                return pop1.next;
            }
             
            if(stack1.size()==0 && stack2.size()==0){
                return pHead1;
            }
             
            if((stack1.size()==0 && stack2.size()!=0) || (stack1.size()!=0 && stack2.size()==0)){
                return pop1;
            }
 
        }
        return null;
    }
}

解法3-先后指针

两个易错点。
(1)指针用完了,再次使用时要归位置;
(2)if(){} else{}大条件下后面不用再去对没找到的情况进行空值返回。当时在if内部条件中得做相应的处理。本题中的体现在于两个指针都走到最后了,没有相同的结点。
nowcoder的AC
提交时间:2020-01-06 语言:Java 运行时间: 22 ms 占用内存:9380K 状态:答案正确

/*
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) {
        ListNode node1 = pHead1;
        ListNode node2 = pHead2;
         
        if(pHead1==null || pHead2==null){
            return null;
        }
        int count1=0;
        int count2=0;
         
        while(node1!=null){
            count1++;
            node1=node1.next;
        }
         
        while(node2!=null){
            count2++;
            node2=node2.next;
        }
         
        //attention! pointer return position
        node1=pHead1;
        node2=pHead2;
         
        if(count1>=count2){
            int count=count1-count2;
            for(int i=0;i<count;i++){
                node1=node1.next;
            }
            while(node1!=node2){
                node1=node1.next;
                node2=node2.next;
                if(node1==null && node2==null){
                    return null;
                }
            }
            return node1;
        }else{
            int count=count2-count1;
            for(int i=0;i<count;i++){
                node2=node2.next;
            }
            while(node1!=node2){
                node1=node1.next;
                node2=node2.next;
                if(node1==null && node2==null){
                    return null;
                }
            }
            return node1;
        }
        //return null;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值