环形链表_Java语言编写

相交链表

输入两个链表,找出它们的第一个公共结点
在这里插入图片描述
示例1:
在这里插入图片描述

输入:intersectVal=8,listA=[4,1,8,4,5],listB=[5,0,1,8,4,5],
      skipA=2,skipB=3
输出:Reference of the node with value=8
输入解释:相交结点的值为8(注意:如果两个列表相交则不能为0)。
         从各自的表头开始算起,链表 A 为[4,1,8,4,5],链表 B 为[5,0,1,8,4,5]。
         在 A 中,相交结点前有 2 个结点;在 B 中,相交结点前有 3 个结点。

示例2:
在这里插入图片描述

输入:intersectVal=2,listA=[0,9,1,2,4],listB=[3,2,4],
      skipA=3,skipB=1
输出:Reference of the node with value=2
输入解释:相交结点的值为2(注意:如果两个列表相交则不能为0)。
         从各自的表头开始算起,链表 A 为[0,9,1,2,4],链表 B 为[3,2,4]。
         在 A 中,相交结点前有 3 个结点;在 B 中,相交结点前有 1 个结点。

示例3:
在这里插入图片描述

输入:intersectVal=0,listA=[2,6,4],listB=[1,5],
      skipA=3,skipB=2
输出:null
输入解释:从各自的表头开始算起,链表 A 为[2,6,4],链表 B 为[1,5]。
         由于这两个链表不相交,所以intersectVal必须为0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。         
注意:
1.如果两个链表没有交点,返回 null;
2.在返回结果后,两个链表仍必须保持原有的结构;
3.可假定整个链表结构中没有循环;
4.程序尽量满足O(n)时间复杂度,且仅用O(1)内存。

思路:

1.先各自求出链表的长度
2.让长的先走 长度差步
3.同时走,第一次相遇时,就是交点
private int getLength(ListNode head) {
    int len = 0;
    for (ListNode c = head; c != null; c = c.next) {
        len++;
    }

    return len;
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    int lenA = getLength(headA);
    int lenB = getLength(headB);

    ListNode longer = headA;
    ListNode shorter = headB;
    int diff = lenA - lenB;
    if (lenA < lenB) {
        longer = headB;
        shorter = headA;
        diff = lenB - lenA;
    }

    for (int i = 0; i < diff; i++) {
        longer = longer.next;
    }

    while (longer != shorter) {
        longer = longer.next;
        shorter = shorter.next;
    }

    return longer;
}

环形链表

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。

示例1:
在这里插入图片描述
示例2:
在这里插入图片描述
示例3:
在这里插入图片描述

快慢指针:
快的一次 2 步,慢的一次 1 步

问:快的一次 3 步或者 n(>=3) 步?
答:不可以,可能会一直错过

办法:
1.把带环转为相交问题
2.一个引用从起点出发
  一个引用从相遇点出发
  一定会在环的入口点相遇
证明:
   1.慢引用走的距离   L+C
   2.快引用走的距离   L+C+(n+1)*R
   3.快引用走的距离   2*(L+C)=2L+2C
     2L+2C = L+C+(n+1)*R
         L = nR+(R-C)  

1.快慢指针(一个1步,一个2步,不能1步,一个n步,因为可能会错过)
2.如果相遇,带环;如果快的遇到null,不带环
3.求入环点
    1.转化为相交问题
    2.一个从起点出发,一个从相遇点出发,都走一步,一定相遇在入环点

思路:

        // 求相遇点
        // 如果快的遇到 null,表示没有环,直接返回 null
        // 相遇点出发 + 起点出发,最终相遇
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        // fast 遇到 null,表示不带环,返回 null
        // fast == slow,表示遇到相遇点了
        do {
            if (fast == null) {
                return null;
            }
            fast = fast.next;
            if (fast == null) {
                return null;
            }
            fast = fast.next;
            slow = slow.next;
        } while (fast != slow);
        
        ListNode p = head;
        ListNode q = slow;
        while (p != q) {
            p = p.next;
            q = q.next;
        }
        
        return p;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值