Linked List Cycle II

19 篇文章 0 订阅
14 篇文章 0 订阅

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:

Can you solve it without using extra space?

 题意:给定一个链表,判断链表的环的起点,如果没有则返回null

解题思路:(1)用快慢指针的方法判断链表是否有环,如果有,求出快慢指针第一次相遇的节点。
 (2)从相遇节点之后把原链表分成两个部分,把问题转化为求两个链表相交的第一个节点

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) {
			return null;
		}
        ListNode fast = head;
        ListNode slow = head;
        ListNode head1 = head;
        ListNode head2 = null;
        //求出快慢指针第一次相遇的节点
        while (fast.next != null && fast.next.next != null) {
        	fast = fast.next.next;
        	slow = slow.next;
        	if (fast == slow ) {
        	    //确定第二个链表的表头。并将原链表相遇节点指向null
				head2 = slow.next;
				slow.next = null;break;
			}
		}
        if (fast != slow) {
			return null;
		}
        //问题转化为求两个链表的相交部分的第一个节点
        ListNode curNode1 = head1;
        ListNode curNode2 = head2;
    
        int length1 = 1, length2 = 1;
        while (curNode1.next != null) {
			length1++;
			curNode1 = curNode1.next;
		}
        while (curNode2.next != null) {
			length2++;
			curNode2 = curNode2.next;
		}
        curNode1 = head1;
        curNode2 = head2;
        int count = Math.abs(length1 - length2);
        if (length1 >= length2) {
			while (count > 0) {
				curNode1 = curNode1.next;
				count--;
			}
		}else {
			while (count > 0) {
				curNode2 = curNode2.next;
				count--;
			}
		}
        while (curNode1 != curNode2) {
			curNode1 = curNode1.next;
			curNode2 = curNode2.next;
		}
        return curNode1;
	
    }
}

第二个思路:这个方法比上面的方法运行时间快

入下图,第一次相遇时slow走过的距离为a+b,fast走过的距离为a+b+c+b。

因为fast的速度是slow的两倍,所以fast走的距离是slow的两倍,有 2(a+b) = a+b+c+b,可以得到a=c。

也就是从head到环开始的路程 = 从相遇节点到环开始的路程

那么,只要Slow和Fast相遇了,就拿一个从头开始走,一个从相遇的节点开始走

两个都走一步,那么再次相遇必定是环的开始节点



/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) {
			return null;
		}
        ListNode fast = head;
        ListNode slow = head;
        ListNode head1 = head;
        ListNode head2 = head;
        //求出快慢指针第一次相遇的节点
        while (fast.next != null && fast.next.next != null) {
        	fast = fast.next.next;
        	slow = slow.next;
        	if (fast == slow ) {
				head2 = slow;
				break;
			}
		}
        if (fast != slow) {
			return null;
		}
        while (head1 != head2) {
			head1 = head1.next;
			head2 = head2.next;
		}
        return head1;
	
	
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值