160. 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.

链接:  http://leetcode.com/problems/intersection-of-two-linked-lists/

题解:

题目理解起来比较容易,两个单链表求交叉点。数学上来讲使用两个runner,一个链表走完以后继续走另外一个链表,假如有交叉点则两个节点相等的时候正好走了相同的距离。这道题目还要加入对表尾元素的判断,假如表尾元素不相等则可以立刻返回null。这里所说的相等是指两个instance是否指向同一个reference,Java里面用 ==以及 != 来判断两个reference的Identity,就是是否指向同一元素。假如要比较两个元素内容的相同,一般要override  equals()方法以及hashCode()方法,假如没有定义equals,则系统默认会使用==来比较。有机会还要对iterator,comparator,comparable,serilizable,runnable,throwable等等class和interface加以学习。

Time Complexity - O(m + n), Space Complexity - O(1)。

/**
 * 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, tailB = null;
        ListNode nodeA = headA, nodeB = headB;
        
        while(true) {
            if(nodeA == null)
                nodeA = headB;
            if(nodeB == null)
                nodeB = headA;
            if(nodeA.next == null)
                tailA = nodeA;
            if(nodeB.next == null)
                tailB = nodeB;
            if(tailA != null && tailB != null && tailA != tailB)
                return null;
            if(nodeA == nodeB)
                return nodeA;
                            
            nodeA = nodeA.next;
            nodeB = nodeB.next;
        }
    }
}

 

二刷:

两个单链表求交点。这道题目一刷怎么过的不知道。不过还是自己二刷写的版本比较对自己的脑回路。

  1. 因为listA和listB的长度可能会不一致,所以我们可以人为地让两个runner走过同样的路径,然后进行对比是否相等来确定交点。
  2. 首先定义nodeA和nodeB,以及空的tailA和tailB
  3. 接下来我们在nodeA != null以及nodeB != null的情况下同时遍历两个单链表
  4. 当两个runner.next != null时,我们只管让runner = runner.next
  5. 否则,这是runner.next等于null,这个时候我们分别记录下尾节点tailA和tailB,然后设置nodeA = headB, nodeB = headA,分别让两个runner继续遍历另外一个链表
  6. 当tailA和tailB均非空时,也就是说我们的nodeA和nodeB现在均已经遍历完了自己首先被分配的链表,正在另一条链表上继续工作时
    1. 这个时候我们可以进行判断, 当tailA.val != tailB.val的时候,说明两个单链表肯定没有交点,我们直接返回null
    2. 否则,我们继续判断nodeA.val是否等于nodeB.val,假如相等的话,此时的nodeA或者nodeB一定是交点。 因为两个runner都已经走过了2 x 两条链表不同的部分 + 1 x 两条链表相交的部分,剩下的就是1 x 两条链表相交的部分

Java:

/**
 * 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 nodeA = headA, nodeB = headB, tailA = null, tailB = null;
        while (nodeA != null && nodeB != null) {
            if (nodeA.next != null) {
                nodeA = nodeA.next;
            } else if (tailA == null){
                tailA = nodeA;
                nodeA = headB;
            }
            if (nodeB.next != null) {
                nodeB = nodeB.next;
            } else if (tailB == null){
                tailB = nodeB;
                nodeB = headA;
            }
            if (tailA != null && tailB != null) {
                 if (tailA.val != tailB.val) {
                     return null;
                 }
                 if (nodeA.val == nodeB.val) {
                     return nodeA;
                 }
            } 
        }
        
        return nodeA;
    }
}

 

三刷:

为什么要在node.next == null以及node.next != null的时候作两种判断呢? 我们可以看例子,假设list1 = {1}, list2 = {1},两链表交集应该是{1}。假如我们把不把node = node.next放在  (node.next != null)的条件里,那么下一次判断的时候我们的node就会等于null。对于各种边界问题还是要好好思考仔细了。

Java:

/**
 * 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 nodeA = headA, nodeB = headB, tailA = null, tailB = null;
        while (nodeA != null && nodeB != null) {
            if (tailA != null && tailB != null) {
                if (tailA != tailB) {
                    return null;    
                }
                if (nodeA == nodeB) {
                    return nodeA;
                }
            }
            if (nodeA.next == null) {
                tailA = nodeA;
                nodeA = headB;
            } else {
                nodeA = nodeA.next;
            }
            if (nodeB.next == null) {
                tailB = nodeB;
                nodeB = headA;
            } else {
                nodeB = nodeB.next;
            }
        }
        return null;
    }
}

 

Update:

/**
 * 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, tailB = null, runnerA = headA, runnerB = headB;
    
        while (runnerA != null && runnerB != null) {
            if (runnerA.next == null) {
                tailA = runnerA;
                runnerA = headB;
            } else {
                runnerA = runnerA.next;
            }
            if (runnerB.next == null) {
                tailB = runnerB;
                runnerB = headA;
            } else {
                runnerB = runnerB.next;
            }
            if (tailA != null && tailB != null) {
                if (tailA != tailB) return null;
                if (runnerA == runnerB) return runnerA;
            }
        }
        return null;
    }
}

 

Reference:

https://en.wikibooks.org/wiki/Java_Programming/Comparing_Objects

http://www.leepoint.net/data/expressions/22compareobjects.html

posted @ 2015-05-09 12:37  YRB  阅读(466)  评论(1编辑  收藏  举报