<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 0092. 反轉鏈表 II ## 題目地址(92. 反轉鏈表 II) <https://leetcode-cn.com/problems/reverse-linked-list-ii/> ## 題目描述 ``` <pre class="calibre18">``` 反轉從位置 m 到 n 的鏈表。請使用一趟掃描完成反轉。 說明: 1 ≤ m ≤ n ≤ 鏈表長度。 示例: 輸入: 1->2->3->4->5->NULL, m = 2, n = 4 輸出: 1->4->3->2->5->NULL ``` ``` ## 前置知識 - 鏈表 ## 公司 - 阿里 - 騰訊 - 百度 - 字節 ## 思路(四點法) 這道題和[206.reverse-linked-list](https://github.com/azl397985856/leetcode/blob/master/problems/206.reverse-linked-list.md) 有點類似,并且這道題是 206 的升級版。 讓我們反轉某一個區間,而不是整個鏈表,我們可以將 206 看作本題的特殊情況(special case)。 核心在于**取出需要反轉的這一小段鏈表,反轉完后再插入到原先的鏈表中。** 以本題為例: 反轉的是 2,3,4 這三個點,那么我們可以先取出 2,用 cur 指針指向 2,然后當取出 3 的時候,我們將 3 指向 2 的,把 cur 指針前移到 3,依次類推,到 4 后停止,這樣我們得到一個新鏈表 4->3->2, cur 指針指向 4。 對于原鏈表來說,有兩個點的位置很重要,需要用指針記錄下來,分別是 1 和 5,把新鏈表插入的時候需要這兩個點的位置。用 pre 指針記錄 1 的位置當 4 結點被取走后,5 的位置需要記下來 這樣我們就可以把反轉后的那一小段鏈表加入到原鏈表中 ![](https://img.kancloud.cn/cc/e4/cce4638062603b883631e60f34bfd0e3_956x535.gif) (圖片來自網絡) - 首先我們直接返回 head 是不行的。 當 m 不等于 1 的時候是沒有問題的,但只要 m 為 1,就會有問題。 - 其次如果鏈表商都小于 4 的時候,p1,p2,p3,p4 就有可能為空。為了防止 NPE,我們也要充分地判空。 ``` <pre class="calibre18">``` <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reverseBetween</span><span class="hljs-params">(self, head: ListNode, m: int, n: int)</span> -> ListNode:</span> pre = <span class="hljs-keyword">None</span> cur = head i = <span class="hljs-params">0</span> p1 = p2 = p3 = p4 = <span class="hljs-keyword">None</span> <span class="hljs-title"># 一坨邏輯</span> <span class="hljs-keyword">if</span> p1: p1.next = p3 <span class="hljs-keyword">else</span>: dummy.next = p3 <span class="hljs-keyword">if</span> p2: p2.next = p4 <span class="hljs-keyword">return</span> head ``` ``` 如上代碼是不可以的,我們考慮使用 dummy 節點。 ``` <pre class="calibre18">``` <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reverseBetween</span><span class="hljs-params">(self, head: ListNode, m: int, n: int)</span> -> ListNode:</span> pre = <span class="hljs-keyword">None</span> cur = head i = <span class="hljs-params">0</span> p1 = p2 = p3 = p4 = <span class="hljs-keyword">None</span> dummy = ListNode(<span class="hljs-params">0</span>) dummy.next = head <span class="hljs-title"># 一坨邏輯</span> <span class="hljs-keyword">if</span> p1: p1.next = p3 <span class="hljs-keyword">else</span>: dummy.next = p3 <span class="hljs-keyword">if</span> p2: p2.next = p4 <span class="hljs-keyword">return</span> dummy.next ``` ``` 關于鏈表反轉部分, 順序比較重要,我們需要: - 先 cur.next = pre - 再 更新 p2 和 p2.next(其中要設置 p2.next = None,否則會互相應用,造成無限循環) - 最后更新 pre 和 cur 上述的順序不能錯,不然會有問題。原因就在于`p2.next = None`,如果這個放在最后,那么我們的 cur 會提前斷開。 ``` <pre class="calibre18">``` <span class="hljs-keyword">while</span> cur: i += <span class="hljs-params">1</span> <span class="hljs-keyword">if</span> i == m - <span class="hljs-params">1</span>: p1 = cur next = cur.next <span class="hljs-keyword">if</span> m < i <= n: cur.next = pre <span class="hljs-keyword">if</span> i == m: p2 = cur p2.next = <span class="hljs-keyword">None</span> <span class="hljs-keyword">if</span> i == n: p3 = cur <span class="hljs-keyword">if</span> i == n + <span class="hljs-params">1</span>: p4 = cur pre = cur cur = next ``` ``` ## 關鍵點解析 - 四點法 - 鏈表的基本操作 - 考慮特殊情況 m 是 1 或者 n 是鏈表長度的情況,我們可以采用虛擬節點 dummy 簡化操作 - 用四個變量記錄特殊節點, 然后操作這四個節點使之按照一定方式連接即可。 - 注意更新 current 和 pre 的位置, 否則有可能出現溢出 ## 代碼 我把這個方法稱為 `四點法` 語言支持:JS, Python3 JavaScript Code: ``` <pre class="calibre18">``` <span class="hljs-title">/* * @lc app=leetcode id=92 lang=javascript * * [92] Reverse Linked List II * * https://leetcode.com/problems/reverse-linked-list-ii/description/ */</span> <span class="hljs-title">/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */</span> <span class="hljs-title">/** * @param {ListNode} head * @param {number} m * @param {number} n * @return {ListNode} */</span> <span class="hljs-keyword">var</span> reverseBetween = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">head, m, n</span>) </span>{ <span class="hljs-title">// 虛擬節點,簡化操作</span> <span class="hljs-keyword">const</span> dummyHead = { next: head, }; <span class="hljs-keyword">let</span> cur = dummyHead.next; <span class="hljs-title">// 當前遍歷的節點</span> <span class="hljs-keyword">let</span> pre = cur; <span class="hljs-title">// 因為要反轉,因此我們需要記住前一個節點</span> <span class="hljs-keyword">let</span> index = <span class="hljs-params">0</span>; <span class="hljs-title">// 鏈表索引,用來判斷是否是特殊位置(頭尾位置)</span> <span class="hljs-title">// 上面提到的四個特殊節點</span> <span class="hljs-keyword">let</span> p1 = (p2 = p3 = p4 = <span class="hljs-params">null</span>); <span class="hljs-keyword">while</span> (cur) { <span class="hljs-keyword">const</span> next = cur.next; index++; <span class="hljs-title">// 對 (m - n) 范圍內的節點進行反轉</span> <span class="hljs-keyword">if</span> (index > m && index <= n) { cur.next = pre; } <span class="hljs-title">// 下面四個if都是邊界, 用于更新四個特殊節點的值</span> <span class="hljs-keyword">if</span> (index === m - <span class="hljs-params">1</span>) { p1 = cur; } <span class="hljs-keyword">if</span> (index === m) { p2 = cur; } <span class="hljs-keyword">if</span> (index === n) { p3 = cur; } <span class="hljs-keyword">if</span> (index === n + <span class="hljs-params">1</span>) { p4 = cur; } pre = cur; cur = next; } <span class="hljs-title">// 兩個鏈表合并起來</span> (p1 || dummyHead).next = p3; <span class="hljs-title">// 特殊情況需要考慮</span> p2.next = p4; <span class="hljs-keyword">return</span> dummyHead.next; }; ``` ``` Python Code: ``` <pre class="calibre18">``` <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reverseBetween</span><span class="hljs-params">(self, head: ListNode, m: int, n: int)</span> -> ListNode:</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> head.next <span class="hljs-keyword">or</span> n == <span class="hljs-params">1</span>: <span class="hljs-keyword">return</span> head dummy = ListNode() dummy.next = head pre = <span class="hljs-keyword">None</span> cur = head i = <span class="hljs-params">0</span> p1 = p2 = p3 = p4 = <span class="hljs-keyword">None</span> <span class="hljs-keyword">while</span> cur: i += <span class="hljs-params">1</span> next = cur.next <span class="hljs-keyword">if</span> m < i <= n: cur.next = pre <span class="hljs-keyword">if</span> i == m - <span class="hljs-params">1</span>: p1 = cur <span class="hljs-keyword">if</span> i == m: p2 = cur <span class="hljs-keyword">if</span> i == n: p3 = cur <span class="hljs-keyword">if</span> i == n + <span class="hljs-params">1</span>: p4 = cur pre = cur cur = next <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> p1: dummy.next = p3 <span class="hljs-keyword">else</span>: p1.next = p3 p2.next = p4 <span class="hljs-keyword">return</span> dummy.next ``` ``` **復雜度分析** - 時間復雜度:O(N)O(N)O(N) - 空間復雜度:O(1)O(1)O(1) ## 相關題目 - [25.reverse-nodes-in-k-groups](25.reverse-nodes-in-k-groups-cn.md) - [206.reverse-linked-list](206.reverse-linked-list.html) 更多題解可以訪問我的 LeetCode 題解倉庫:<https://github.com/azl397985856/leetcode> 。 目前已經 37K star 啦。 關注公眾號力扣加加,努力用清晰直白的語言還原解題思路,并且有大量圖解,手把手教你識別套路,高效刷題。 ![](https://img.kancloud.cn/a3/63/a363818092b0356fbd67882f0389528b_900x500.jpg)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看