[LeetCode]Linked List Cycle II

本文介绍了一种高效的方法来确定链表中循环的起始节点,通过使用快慢指针并结合数学分析,避免了额外空间的使用,实现了O(n)的时间复杂度。

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

Follow up:

Can you solve it without using extra space?

Analysis

First, think strightforward, use Linked List Cycle I method, to see if there is cycle. if does, scan from start node for each node to check whether it is in a cycle, this is O(n^2). But think deeply, this is mathmatical question.

Like the picture shows below: assume linked list has cycle,the length of cycle is Y,the length outside cycle is X.

image

two pointers, one goes one step per time, another goes two steps per time. If they went t times and meet at the K node

for pointer 1: t = X+nY+K

for pointer 2: 2t = X+mY+K (m,n is unknown)

From above equation, we could get:

2X + 2nY + 2K = X + mY + K

=>   X+K  =  (m-2n)Y 

It is clear that the relationship between X and K is complementary based on Y. Which is to say, if pointer 1 goes X steps from start node and pointer 2 goes

X steps form K node. They will meet at the start place of cycle. Complexity is O(n)


Java

public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
        	slow = slow.next;
        	fast = fast.next.next;
        	if(slow == fast)
        		break;
        }
        if(fast == null || fast.next == null)
        	return null;
        slow = head;
        while(slow != fast){
        	slow = slow.next;
        	fast = fast.next;
        }
        return fast;
    }

c++

ListNode *detectCycle(ListNode *head) {
        ListNode *slow = head;
    ListNode *fast = head;
    while(fast != NULL && fast->next != NULL){
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
            break;
    }
    if(fast == NULL || fast->next == NULL)
        return NULL;
    slow = head;
    while(slow != fast){
        slow = slow->next;
        fast = fast->next;
    }
    return fast;
    }



LeetCode是一个知名的在线编程平台,提供大量算法和数据结构相关的编程题目,帮助程序员提升编程技能和准备技术面试。 ### 平台介绍 - **题目资源丰富**:涵盖《剑指 Offer》系列等众多类型题目。《剑指 Offer》系列在线题目可在https://leetcode-cn.com/problemset/lcof/ 查看,还有力扣 (LeetCode) 全部题目等丰富资源[^1]。 - **支持多种编程语言**:可以使用常见的编程语言如Python、Java、C++等进行题目的解答。 ### 题目解答示例 - **环形链表判定(Java实现)**:通过遍历链表,检查是否存在节点的下一个节点指向之前遍历过的节点来判断是否为环形链表。 ```java /** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { ListNode node = head; ListNode preNode = head; while (node.next != null) { boolean cycle = false; while (preNode != node) { // System.out.println("val = " + preNode.val); if (node.next == preNode) { return true; } preNode = preNode.next; } // System.out.println("cycle = " + cycle); //if (cycle) { // return true; //} node = node.next; preNode = head; } return false; } } ``` - **环形链表判定(C语言实现)**:使用快慢指针的方法,快指针一次走两步,慢指针一次走一步,如果是环形链表,快慢指针最终会相遇。 ```c /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ //环形链表首先就要想到一个概念 快慢指针 所以这题使用快慢指针 bool hasCycle(struct ListNode *head) { //设置快指针和慢指针 struct ListNode *fast,*slow; fast=head; slow=head; //若是环形链表,指针会无限循环 故结束条件为是否是NULL while(fast!=NULL&&slow!=NULL){ if(fast->next==NULL) return false; //这一步是为了防止访问NULL的空间 fast=fast->next->next; //快指针一次走两步 slow=slow->next; //慢指针一次走一步 if(slow==fast){ //若快慢指针能相遇 就一定是环形链表 return true; } } return false; //退出while就一定有指针到了NULL 所以不是环形链表 } ``` ### 使用方法 - **注册登录**:访问LeetCode官网,注册账号并登录。 - **选择题目**:在题目列表中选择想要解答的题目,可以根据题目类型、难度等进行筛选。 - **编写代码**:选择合适的编程语言,在代码编辑区域编写解答代码。 - **提交代码**:编写完成后,点击提交按钮,系统会对代码进行测试和评判,给出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值