<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ?LeetCode刷題實戰(zhàn)92:反轉(zhuǎn)鏈表 II

          共 2831字,需瀏覽 6分鐘

           ·

          2020-11-10 20:26

          算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎(chǔ)知識和業(yè)務(wù)邏輯面試+算法面試。所以,為了提高大家的算法能力,這個公眾號后續(xù)每天帶大家做一道算法題,題目就從LeetCode上面選 !

          今天和大家聊的問題叫做?反轉(zhuǎn)鏈表 II,我們先來看題面:

          https://leetcode-cn.com/problems/reverse-linked-list-ii/

          Reverse a linked list from position m to n. Do it in one-pass.


          Note: 1 ≤ m ≤ n ≤ length of list.

          題意


          反轉(zhuǎn)從位置 m 到 n 的鏈表。請使用一趟掃描完成反轉(zhuǎn)。
          說明:1 ≤ m ≤ n ≤ 鏈表長度。

          樣例

          輸入: 1->2->3->4->5->NULL, m = 2, n = 4
          輸出: 1->4->3->2->5->NULL


          解題

          https://www.cnblogs.com/techflow/p/13541281.html

          題解

          這題的題意很直接,就是讓我們翻轉(zhuǎn)鏈表當(dāng)中指定的部分,并且只能通過一次遍歷完成。
          我們很容易想明白,通過m和n我們可以將鏈表分成三個部分:
          分別是m左側(cè)的,m到n之間的也就是我們需要翻轉(zhuǎn)的部分,以及n右側(cè)的部分。當(dāng)然這里可能存在一個特殊情況,m左側(cè)和n的右側(cè)都有可能沒有元素,我們可以先忽略,先考慮最一般的情況。
          翻轉(zhuǎn)鏈表我們最常用的方法就是先把[m, n]區(qū)間里的元素先存儲起來,人工翻轉(zhuǎn)了之后,再重新構(gòu)建成一段鏈表,替換原鏈表對應(yīng)的部分。但是很明顯也可以發(fā)現(xiàn),這樣做是不符合題目要求的。因為我們存儲元素遍歷了鏈表一次,我們在構(gòu)建鏈表的時候又遍歷了一次,至少需要兩次遍歷才可以完成
          那怎么樣才能一次遍歷完成鏈表的翻轉(zhuǎn)呢?其實也很簡單,我們只需要倒敘插入就好了。
          比如我們有這樣一段鏈表,我們想要翻轉(zhuǎn)其中2、3、4這三個節(jié)點:
          首先,我們從1開始,1是翻轉(zhuǎn)之后的起始部分。我們先記錄下1的位置,這里1指向2保持不變。對于2號節(jié)點我們需要記錄下它的后繼,這里我們用tmp記錄2號節(jié)點的后繼,也就是3號節(jié)點。之后我們將2號節(jié)點的后繼置為None。
          再下一步,我們用tmp記錄3號節(jié)點的后繼,將3號節(jié)點的后繼指向2號節(jié)點。
          最后,我們?nèi)绶ㄅ谥?,?號節(jié)點的后繼指向3號節(jié)點,將1號節(jié)點的后繼指向4號節(jié)點,并且將2號節(jié)點的后繼指向4號節(jié)點的原后繼,也就是None。這樣我們就完成了鏈表部分的翻轉(zhuǎn),其中的原理很簡單,就是利用了鏈表遍歷和插入時候的性質(zhì),每次將需要翻轉(zhuǎn)部分元素的后繼指向它們原本的前驅(qū)。這句話有些拗口,但是多讀幾遍也就理解了。
          這個思路非常簡單,但是用代碼實現(xiàn)卻不容易,很容易寫錯。尤其是在賦值的時候,很容易搞錯指針到底應(yīng)該指向哪里,到底需要哪些臨時變量。關(guān)于這些內(nèi)容沒有太好的辦法,只能加強訓(xùn)練,提升自己的基本功。
          最后, 我們考慮一下特殊情況。題目當(dāng)中的特殊情況有兩種, 第一種是m=1,第二種是n=鏈表末尾。其中第二種不算是特殊情況,因為在鏈表當(dāng)中末尾的元素也有后繼,就是None。但是m=1的情況需要小心,因為m=1的時候,翻轉(zhuǎn)部分是沒有前驅(qū)的,稍稍有些不同。解決也很簡單,我們單獨特判一下這種情況,人為創(chuàng)建一個前驅(qū)節(jié)點即可。
          貼上代碼:

          class?Solution:
          ????def?reverseBetween(self, head:?ListNode, m:?int, n:?int)?-> ListNode:
          ????????if?m == n:
          ????????????return?head
          ????????
          ????????pnt = head
          ????????# 移動m-2格,到達翻轉(zhuǎn)部分的前驅(qū)節(jié)點
          ????????for?i in?range(m-2):
          ????????????pnt = pnt.next
          ????????????
          ????????
          ????????flag = False
          ????????# 特判m=1的情況,如果m=1那么人為制造一個節(jié)點作為前驅(qū)
          ????????if?m == 1:
          ????????????flag = True
          ????????????pnt = ListNode(0)
          ????????????pnt.next?= head
          ????????????head = pnt
          ????????????
          ????????# cur即當(dāng)前待翻轉(zhuǎn)的節(jié)點
          ????????cur = pnt.next
          ????????# pre表示cur的前驅(qū)
          ????????pre = pnt
          ????????# last表示最后一個翻轉(zhuǎn)的元素
          ????????last = pnt.next
          ????????????
          ????????for?i in?range(m, n+1):
          ????????????# 先記錄下當(dāng)前節(jié)點的后繼
          ????????????nxt = cur.next
          ????????????# 將當(dāng)前節(jié)點的后繼指向前驅(qū)
          ????????????cur.next?= pre
          ????????????pnt.next?= cur
          ????????????pre = cur
          ????????????cur = nxt
          ????????????
          ????????# 將last指向翻轉(zhuǎn)之后的元素,將鏈表串起來
          ????????last.next?= cur
          ????????return?head.next?if?flag else?head

          總結(jié)

          鏈表的相關(guān)操作非常考驗基本功,雖然算法簡單,但是對鏈表不熟悉,邏輯思考能力稍稍弱一些的同學(xué)想要做出這道題還是比較困難的。也因此,很多公司在面試的時候喜歡詢問鏈表相關(guān)的操作和算法,以此考察候選人的基本功。如果想要進入大公司的,建議好好練習(xí)一下相關(guān)的問題,一定會有幫助的。
          好了,今天的文章就到這里,如果覺得有所收獲,請順手點個在看或者轉(zhuǎn)發(fā)吧,你們的支持是我最大的動力。


          上期推文:

          LeetCode50-80題匯總,速度收藏!
          LeetCode刷題實戰(zhàn)81:搜索旋轉(zhuǎn)排序數(shù)組 II
          LeetCode刷題實戰(zhàn)82:刪除排序鏈表中的重復(fù)元素 II
          LeetCode刷題實戰(zhàn)83:刪除排序鏈表中的重復(fù)元素
          LeetCode刷題實戰(zhàn)84:?柱狀圖中最大的矩形
          LeetCode刷題實戰(zhàn)85:最大矩形
          LeetCode刷題實戰(zhàn)86:分隔鏈表
          LeetCode刷題實戰(zhàn)87:擾亂字符串
          LeetCode刷題實戰(zhàn)88:合并兩個有序數(shù)組
          LeetCode刷題實戰(zhàn)89:格雷編碼
          LeetCode刷題實戰(zhàn)90:子集 II
          LeetCode刷題實戰(zhàn)91:解碼方法

          瀏覽 49
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  啊v在线| 免费三级片网址 | 色偷偷伊人 | 波多野结衣在线观看一区二区 | 精品国产白色丝袜高跟鞋 |