每天一道leetcode142-尋找連結串列中環的入口

公眾號_程式設計師喬戈裡發表於2019-02-27

考試結束,班級平均分只拿到了年級第二,班主任於是問道:大家都知道世界第一高峰珠穆朗瑪峰,有人知道世界第二高峰是什麼嗎?正當班主任要繼續發話,只聽到角落默默想起來一個聲音:”喬戈裡峰

前言

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打卡群與技術交流群,歡迎關注。

相關文章