每天一道leetcode142-寻找链表中环的入口

考试结束,班级平均分只拿到了年级第二,班主任于是问道:大家都知道世界第一高峰珠穆朗玛峰,有人知道世界第二高峰是什么吗?正当班主任要继续发话,只听到角落默默想起来一个声音:”乔戈里峰

前言

2018.11.11号打卡
明天的题目:
https://leetcode-cn.com/problems/sort-array-by-parity/

题目

每天一道leetcode142-寻找链表中环的入口
分类:链表
中文链接:
https://leetcode-cn.com/problems/linked-list-cycle-ii/
英文链接
https://leetcode.com/problems/linked-list-cycle-ii/

题目详述

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
说明:不允许修改给定的链表。
进阶:
你是否可以不用额外空间解决此题?

题目详解

使用额外空间的思路

  • 就是使用一个hashmap,去遍历一遍链表,每遍历一个链表,如果不存在这个节点,那么就插入hashmap,如果存在,说明这个节点已经插入了,那么这个节点就是重复的节点,为啥重复了,就是环的入口节点了。

代码

 1/**
2 * Definition for singly-linked list.
3 * class ListNode {
4 *     int val;
5 *     ListNode next;
6 *     ListNode(int x) {
7 *         val = x;
8 *         next = null;
9 *     }
10 * }
11 */
12public class Solution {
13    public ListNode detectCycle(ListNode head) {
14        HashMap<ListNode,Integer> map = new HashMap<>();
15        if(head == null || head.next == null)
16            return null;
17        while(head != null)
18        {
19            if(map.containsKey(head) == false)
20            {
21                map.put(head,1);
22                head = head.next;
23            }else{
24                return head;
25            }
26        }
27        return null;
28    }
29}
复制代码

代码讲解

  • 15-22行,hashmap判断这个节点如果不存在,那么插入到hashmap里面;
  • 23-24行,hashmap中存在这个节点,那么就返回这个节点,也就是入口节点

不使用额外空间的思路

  • 使用快慢指针,快指针每次走两步,慢指针每次走一步,如果快慢指针相遇说明有环;
  • 有环以后,需要寻找环入口节点,已经找到了一个环的中的节点,利用这个节点,去往下遍历,由于是环,所以这个节点肯定会和自身相遇,相遇以后,记录相遇过程中走的步数,就是环的长度
  • 知道环的长度以后,然后再利用快慢指针的思想,快指针先走环长度,然后快慢指针再一起走,这样因为快指针先走了环的长度,当两者相遇肯定是环的入口节点相遇(为啥呢,因为快慢指针肯定会进入环里面,而由于快指针先走了环的长度,所以也就是一个周期,所以只要进入环,那么这两个指针必然相遇

代码

 1/**
2 * Definition for singly-linked list.
3 * class ListNode {
4 *     int val;
5 *     ListNode next;
6 *     ListNode(int x) {
7 *         val = x;
8 *         next = null;
9 *     }
10 * }
11 */
12public class Solution {
13    boolean flag = true;
14    public ListNode detectCycle(ListNode head)
15    {
16        ListNode pHead = head;
17        if(pHead == null || pHead.next == null)
18            return null;
19        ListNode pNode = judgeHasChain(pHead);
20        if(pNode != null)
21        {
22            int lengthChain = 1;
23            ListNode pNodeCopy = pNode.next;
24            while(pNodeCopy != pNode)
25            {
26                lengthChain++;
27                pNodeCopy = pNodeCopy.next;
28            }
29            ListNode fast = pHead;
30            ListNode slow = pHead;
31            int temp = 0;
32            while(temp < lengthChain)
33            {
34                fast = fast.next;
35                temp++;
36            }
37            while(fast != slow)
38            {
39                fast = fast.next;
40                slow = slow.next;
41            }
42            return fast;
43        }
44        return null;
45    }
46    private ListNode judgeHasChain(ListNode pHead)
47    {
48        ListNode fast = pHead.next;
49        ListNode slow = pHead;
50        while(fast != slow)
51        {
52            if(fast != null && fast.next != null)
53            {
54                fast = fast.next;
55            }else{
56                flag = false;
57                break;
58            }
59            if(slow != null && slow.next != null)
60            {
61                slow = slow.next;
62            }else{
63                flag = false;
64                break;
65            }
66            if(fast == slow)
67            {
68                return fast;
69            }else{
70                fast = fast.next;
71            }
72        }
73        if(flag)
74            return fast;
75        return null;
76    }
77}
复制代码

代码讲解

  • 46-76 就是判断链表中是否有环,之前有详细讲过 之前的文章链表:http://t.cn/EANBcf4
  • 19行中,如果链表有环,那么返回的这个节点必然在环中
  • 22-28行,利用19行的节点,遍历计算环的长度
  • 32-36行,快指针先走环长度
  • 37-41行 快慢指针一起走,相遇就是环的入口节点

结束语

2018.11.11号打卡

作者乔戈里亲历2019秋招,哈工大计算机本硕,百度准入职java工程师,欢迎大家关注我的微信公众号:程序员乔戈里,公众号有3T编程资源,以及我和我朋友(准入职百度C++工程师)在秋招期间整理的近200M的面试必考的java与C++面经,并有每天一道leetcode打卡群与技术交流群,欢迎关注。

猜你喜欢

转载自juejin.im/post/5be8058ee51d4536f4451432