zoukankan      html  css  js  c++  java
  • 剑指36.两个链表的第一个公共结点

    题目描述

    输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
     

    思路

            如果两个链表有公共结点,那么两个链表用公共的尾部,如果从两个链表的尾部开始往前比较,那么最后一个相同的节点就是我们要找的节点。

    思路1:利用两个辅助栈。分别把两个链表的节点放入两个栈里,这样两个链表的尾节点就位于两个栈的栈顶,接下来比较两个栈顶的节点是否相同,如果相同,则把栈顶弹出接着比较下一个节点,直到找到最后一个相同的节点。           (时间复杂度O(m+n),空间复杂度O(m+n))

            之所以需要用到栈,是因为想同时遍历达到两个栈的尾节点。因为当两个链表长度不同时,如果从头开始遍历,到达尾节点的时间就不一致。

    思路2:利用长度关系。第一次遍历求出两个链表的长度,第二次遍历时,就让较长的链表先走若干步,接着同时在两个链表上遍历,找到的第一个相同的节点即为所求。     (时间复杂度O(m+n),不需要额外数据结构)

    思路3:利用两个链表的节点和相同。让指向链表1的引用依次指向List1和List2,与此同时,让指向链表2的引用依次指向List2和List1。如果两个链表的长度不相同,但是利用长度和相同,第二次遍历两个引用一定同时相遇。   (非常巧妙!!)

     

    解法1

    public class Solution {
        public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
            if (pHead1 == null || pHead2 == null) return null;
            Stack<ListNode> stack1 = new Stack<ListNode>();
            Stack<ListNode> stack2 = new Stack<ListNode>();
            while (pHead1 != null){
                stack1.push(pHead1);
                pHead1 = pHead1.next;
            }
            while (pHead2 != null){
                stack2.push(pHead2);
                pHead2 = pHead2.next;
            }
            ListNode res = null;
            while (!stack1.isEmpty() && !stack2.isEmpty() && stack1.peek() == stack2.peek()){
                res = stack1.pop();
                stack2.pop();
            }
            return res;
        }
    }

    解法2

    public class Solution {
        // 利用长度关系
        // 要考虑到两个链表没有公共结点的情况!!这样最后要返回null
        public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
            if (pHead1 == null || pHead2 == null) return null;
            // 第一次遍历求出两个链表各自的长度
            int len1 = getLength(pHead1);
            int len2 = getLength(pHead2);
            int len = len1 - len2;  // 长度差
            ListNode longList = pHead1;
            ListNode shortList = pHead2;
            if (len < 0){ // 说明链表2更长
                longList = pHead2;
                shortList = pHead1;
                len = -len;
            }
            for (int i = 0; i < len; i++) {
                longList = longList.next;
            }
            while (longList != null && longList != shortList){  // 如果没有公共结点,则返回null
                longList = longList.next;
                shortList = shortList.next;
            }
            return longList; // 没有公共结点刚好返回null
        }
        private int getLength(ListNode head){
            int len = 0;
            while (head != null){
                head = head.next;
                len++;
            }
            return len;
        }
    }

    解法3

    public class Solution {
        public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
            if(pHead1 == null || pHead2 == null) return null;
            ListNode p1 = pHead1;
            ListNode p2 = pHead2;
            while (p1 != p2){
                p1 = p1 == null ? pHead2 : p1.next;
                p2 = p2 == null ? pHead1 : p2.next;
            }
            return p1;
        }
    }

     Note:

    长度相同有公共结点,第一次就遍历到;没有公共结点,走到尾部NULL相遇,返回NULL
    长度不同有公共结点,第一遍差值就出来了,第二遍一起到公共结点;没有公共,一起到结尾NULL。

  • 相关阅读:
    qt运行时连接signal和slot
    linux使用usb转串口调试ARM开发板
    qwt自定义时间标尺TimeScale
    关于mysql 导入大型数据问题的解决(转载,出处以忘)
    JavaScript replace(RegExp, Function)详解
    有关高度和宽度的对象
    前自增和后自增(chrome js 为了保险,还没测过其它的)
    JavaScript效率PK——统计特定字符在字符串中出现的次数
    getStyle函数
    解决CHM文件在WIN7下崩溃和自动生成CHW文件的问题
  • 原文地址:https://www.cnblogs.com/HuangYJ/p/13540214.html
Copyright © 2011-2022 走看看