码迷,mamicode.com
首页 > 其他好文 > 详细

Intersection of Two Linked Lists

时间:2015-03-05 20:53:54      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:

https://oj.leetcode.com/problems/intersection-of-two-linked-lists/

Write a program to find the node at which the intersection of two singly linked lists begins.

 

For example, the following two linked lists:

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

begin to intersect at node c1.

 

Notes:

    • If the two linked lists have no intersection at all, return null.
    • The linked lists must retain their original structure after the function returns.
    • You may assume there are no cycles anywhere in the entire linked structure.
    • Your code should preferably run in O(n) time and use only O(1) memory.

解题思路:

将headA这个链表的节点全部加入一个set,再对headB这个链表的所有节点看在不在set里,返回第一个在的,或者返回null。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        Set<ListNode> set = new HashSet<ListNode>();
        while(headA != null){
            set.add(headA);
            headA = headA.next;
        }
        
        while(headB != null){
            if(set.contains(headB)){
                return headB;
            }
            headB = headB.next;
        }
        return headB;
    }
}

但是题目要求用O(n)的时间和O(1)的内存,上面的解法花了O(n)的时间和O(n)的内存。思考如何改进。

 观察上图链表的结构,其实只要找出两个链表中较长的那个,较长的那个先往后移动m-n,然后两个节点再每次同时往后移动一个节点,直到它们相等。这样就可以了。这样的时间复杂度是O(3n)。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode traverseA = headA;
        ListNode traverseB = headB;
        int lengthA = 0;
        int lengthB = 0;
        
        while(traverseA != null){
            traverseA = traverseA.next;
            lengthA++;
        }
        while(traverseB != null){
            traverseB = traverseB.next;
            lengthB++;
        }
        
        traverseA = headA;
        traverseB = headB;
        
        if(lengthA > lengthB){
            while(lengthA != lengthB){
                traverseA = traverseA.next;
                lengthA--;
            }
        }else{
            while(lengthA != lengthB){
                traverseB = traverseB.next;
                lengthB--;
            }
        }
        
        while(traverseA != traverseB){
            traverseA = traverseA.next;
            traverseB = traverseB.next;
        }
        
        return traverseA;
    }
}

 

官方的solution里给了另一种很tricky的解法,很不容易想到。

用两个节点分别从两个链表的开头,同时走,A到结尾后,从B的开始继续,同理,B到结尾后从A的开头继续。这样,在第二轮,他们必然会在交接的节点相遇。

如果A和B的最后一个节点不等,他们一定是没有交接点的。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null){
            return null;
        }
        ListNode tailA = null;
        ListNode tailB = null;
        ListNode traverseA = headA;
        ListNode traverseB = headB;
        
        while(true){
            if(traverseA == traverseB){
                return traverseA;
            }
            if(traverseA.next == null){
                tailA = traverseA;
                traverseA = headB;
            }else{
                traverseA = traverseA.next;
            }
            if(traverseB.next == null){
                tailB = traverseB;
                traverseB = headA;
            }else{
                traverseB = traverseB.next;
            }
            
            //注意这个判断,光有tailA!=tailB是不行的,因为这是tailA可能已经到结尾了,而tailB还是null
            if(tailA!= null && tailB != null && tailA != tailB){
                return null;
            }
        }
    }
}

这个解法很巧妙,看下面的图

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

我们令a1-a2=a,c1-c3=c,b1-b3=b
实际上就是a+c+b==b+c+a

 

Intersection of Two Linked Lists

标签:

原文地址:http://www.cnblogs.com/NickyYe/p/4316218.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!