【三次过】Lintcode 380. 两个链表的交叉

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/majichen95/article/details/83820697

请写一个程序,找到两个单链表最开始的交叉节点。

样例

下列两个链表:

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

在节点 c1 开始交叉。

挑战

需满足 O(n) 时间复杂度,且仅用 O(1) 内存。

注意事项

  • 如果两个链表没有交叉,返回null
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。

解题思路:

时间:O(2 * (LenA + LenB)) = O(LenA + LenB)
空间:O(1)
算法:

  1. 分别测量两个链表的长度;
  2. 通过长度比较,令两个链表的头指针都指向 距离末尾节点距离相同 并且 距离最远的地方。其实就是让两个指针指向离交叉点距离相同的位置;
  3. 一起挪动两个指针,知道他们指向同一个节点;
  4. 返回任意一个指针指向的节点。
/**
 * Definition for ListNode
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */

public class Solution {
    /**
     * @param headA: the first list
     * @param headB: the second list
     * @return: a ListNode
     */
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // write your code here
        if(headA == null || headB == null)
            return null;
        
        int lenA = measureLength(headA);
        int lenB = measureLength(headB);
        
        ListNode nodeA = headA;
        ListNode nodeB = headB;
        
        //根据两者长度定比较起始点,使得从起始点开始两者长度一致
        while(lenA < lenB){
            lenB--;
            nodeB = nodeB.next;
        }

        while(lenA > lenB){
            lenA--;
            nodeA = nodeA.next;
        }
        
        //按顺序比较节点
        while(nodeA != nodeB){
            nodeA = nodeA.next;
            nodeB = nodeB.next;
        }
            
        return nodeA;
    }
    
    private int measureLength(ListNode head){
        int len = 0;
        ListNode node = head;
        
        while(node != null){
            len++;
            node = node.next;
        }
        
        return len;
    }
}

猜你喜欢

转载自blog.csdn.net/majichen95/article/details/83820697
今日推荐