【两次过】Lintcode 380. 相交链表

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

样例

下列两个链表:

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

在节点 c1 开始交叉。

挑战

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

注意事项

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

解题思路1:

时间: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;
    }
}

解题思路2:

解决这个问题的关键是,通过某些方式,让 p1 和 p2 能够同时到达相交节点 c1

所以,我们可以让 p1 遍历完链表 A 之后开始遍历链表 B,让 p2 遍历完链表 B 之后开始遍历链表 A,这样相当于「逻辑上」两条链表接在了一起。

如果这样进行拼接,就可以让 p1 和 p2 同时进入公共部分,也就是同时到达相交节点 c1

那你可能会问,如果说两个链表没有相交点,是否能够正确的返回 null 呢?

这个逻辑可以覆盖这种情况的,相当于 c1 节点是 null 空指针嘛,可以正确返回 null。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p1 = headA, p2 = headB;
        
        while(p1 != p2){
            if(p1 != null){
                p1 = p1.next;
            }else{
                p1 = headB;
            }

            if(p2 != null){
                p2 = p2.next;
            }else{
                p2 = headA;
            }
        }

        return p1;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值