leetcode 142. Linked List Cycle II

目录

一、问题描述

二、代码实现

1、使用Set

2、双指针法(快慢指针)


 

https://leetcode.com/problems/linked-list-cycle-ii/

给定一个可能存在环的链表,返回链表中环的入口点。要求空间复杂度为O(1),同时注意不能改动链表。

 

一、问题描述

测试用例:

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

pos为0、1表示环的入口点是第一个元素、第二个元素,pos为-1表示单链表不存在环。

 

二、代码实现

1、使用Set

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    
    public ListNode detectCycle1(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
                 
        HashSet<ListNode> set = new HashSet<>();
        ListNode cur = head;
        while (cur != null) {
            if (!set.contains(cur)) {
                set.add(cur);
            } else {
                return cur;
            }

            cur = cur.next;
        }
             
        return null;
    }

}

2、双指针法(快慢指针)

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    
    public ListNode detectCycle2(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        
        //1、找到快慢指针第一次相遇的节点(即,判断单链表是否存在环)
        //ListNode slow = head, fast = head.next.next; //Time Limit Exceeded
        ListNode slow = head, fast = head;
        ListNode pos = null;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            
            if (slow == fast) {
                //return slow;    
                //slow是第一次相遇点,但第一次相遇点可能不是入环点
                pos = slow;
                break;
            }
        }
        
        
        //pos != null  环存在
        if (pos != null) {
            //2、找到快慢指针再次相遇的节点(即,找到环的入口点)
            slow = head;
            /*
            //[1,2] 0   输出tail connects to node index 1    期待tail connects to node index 0
            while (fast != null && fast.next != null) {
                fast = fast.next;
                slow = slow.next;
                
                if (slow == fast) {
                    return slow;
                }
            }
            */
            /*
            HashSet<ListNode> set = new HashSet<>();
            ListNode cur = head;
            while (cur != null) {
                if (!set.contains(cur)) {
                    set.add(cur);
                } else {
                    return cur;
                }
                
                cur = cur.next;
            }
            */
            
            //while (fast != null && fast.next != null) {
            while (fast != null) {
                if (slow == fast) {
                    return slow;
                }
                
                fast = fast.next;
                slow = slow.next;
            }
                        
        }
        
        //pos = null;  环不存在
        return null;
    }
     
    public ListNode detectCycle_error(ListNode head) {
        if (head == null) {
            return head;    //return null <-> no cycle
        }
        
        //1、找到快慢指针第一次相遇的节点(即,判断单链表是否存在环)
        ListNode slow = head, fast = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            
            if (slow == fast) { //第一次相遇的节点
                break;
            }
        }
        
        //if (slow != fast) { //即,fast.next == null
        //if (fast.next == null) {
        //[1,2] -1  输出tail connects to node index 0  期待no cycle
        if (fast == null || fast.next == null) {
            return null;
        }
        
        //2、找到快慢指针再次相遇的节点(即,找到环的入口点)
        slow = head;
        fast = fast;
        //while (slow != fast) {  //由于存在环,肯定不会走到null,因此这里不加上判断null应该也没问题
        //[1] -1   输出tail connects 头node index 0   期待no cycle
        // while (fast.next != null) {
        //     slow = slow.next;
        //     fast = fast.next;
        //     if (slow == fast) {
        //         break;
        //     }
        // }
        //[1,2] 0   输出tail connects to node index 1    期待tail connects to node index 0
        while (fast.next != null) {
            if (slow == fast) {
                break;
            }
            
            slow = slow.next;
            fast = fast.next;
        }
        //[1] -1    输出tail connects to node index 0 期待no cycle
        
        return slow;
    }
    
}

 

参考:

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44781/Concise-O(n)-solution-by-using-C%2B%2B-with-Detailed-Alogrithm-Description

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-O(1)-space-solution-with-detailed-explanation.

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44793/O(n)-solution-by-using-two-pointers-without-change-anything

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44915/Java-two-pointers-solution

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44822/Java-two-pointer-solution.

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44777/Concise-JAVA-solution-based-on-slow-fast-pointers

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44893/My-two-cents-still-O(1)-memory-and-O(n)-time

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44902/Sharing-my-Python-solution

https://leetcode.com/problems/linked-list-cycle-ii/discuss/44929/Share-my-O(n)-complexity-and-constant-space-code.-Keep-the-original-list.-Any-comments.

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值