<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>

          七十一、去重交換排序鏈表、 求鏈表的中間結(jié)點

          共 4365字,需瀏覽 9分鐘

           ·

          2020-12-29 09:52



          「@Author:Runsen」

          ?

          編程的本質(zhì)來源于算法,而算法的本質(zhì)來源于數(shù)學,編程只不過將數(shù)學題進行代碼化。「---- Runsen」

          ?

          最近在重新梳理學算法的知識,本文為鏈表常見操作復習的總結(jié)文章,會講解常見的鏈表題目實現(xiàn)思路及附上答案,這些題目在leetcode上對應的題號也有給出,好好學習算法吧~

          • 兩兩交換鏈表的節(jié)點
          • 刪除排序鏈表中的重復元素
          • 排序鏈表(重要)
          • 鏈表的中間結(jié)點

          leetcode 對應題號:24,83,148,876

          LeetCode ?第24題:兩兩交換鏈表的節(jié)點

          給定一個鏈表,兩兩交換其中相鄰的節(jié)點,并返回交換后的鏈表。

          示例:?
          給定?1->2->3->4,?你應該返回?2->1->4->3.

          1——2——3——4:我們需要做的就是,將一指向三,將二指向一,如此我們就完成了反轉(zhuǎn),后續(xù)只要一次遍歷即可。

          思路:a,b,pre記錄三個指針,相鄰兩個,相鄰兩個元素前面的一個,第一步將節(jié)點 2 指向節(jié)點 1,然后再將節(jié)點 1 指向節(jié)點三。這一步交換完畢后鏈表變?yōu)?2->1->3->4。在進行下一次交換,將節(jié)點 4 指向節(jié)點 3,節(jié)點3指向none 但是還要注意節(jié)點 1 的指向,節(jié)點 1 要指向節(jié)點 4。

          #?class?ListNode:
          #?????def?__init__(self,?x):
          #?????????self.val?=?x
          #?????????self.next?=?None

          class?Solution:
          ?def?swapPairs(self,head):
          ?????pre,?pre.next?=?self,?head
          ?????while?pre.next?and?pre.next.next:
          ?????????a?=?pre.next
          ?????????b?=?a.next
          ?????????pre.next,b.next?,a.next?=?b,a,b.next
          ?????????pre?=?a
          ?????????
          ?????return??self.next

          eetCode ?第83題:刪除排序鏈表中的重復元素

          給定一個排序鏈表,刪除所有重復的元素,使得每個元素只出現(xiàn)一次。

          示例?1:?
          輸入:?1->1->2
          輸出:?1->2
          示例?2:?
          輸入:?1->1->2->3->3
          輸出:?1->2->3?

          由于輸入的列表已排序,因此我們可以通過將結(jié)點的值與它之后的結(jié)點進行比較來確定它是否為重復結(jié)點。如果它是重復的,我們更改當前結(jié)點的 next 指針,以便它跳過下一個結(jié)點并直接指向下一個結(jié)點之后的結(jié)點。

          如果遇到cur.val和cur.next.val重復,讓cur.next=cur.next.next

          #?Definition?for?singly-linked?list.
          #?class?ListNode:
          #?????def?__init__(self,?x):
          #?????????self.val?=?x
          #?????????self.next?=?None

          class?Solution:
          ????def?deleteDuplicates(self,?head:?ListNode)?->?ListNode:
          ????????h?=?head
          ????????while?head?and?head.next:
          ????????????if?head.val?==?head.next.val:
          ????????????????head.next?=?head.next.next
          ????????????else:
          ????????????????head?=?head.next
          ????????????????
          ????????return?h

          class?Solution:
          ????def?deleteDuplicates(self,?head):
          ????????cur?=?root?=?head
          ????????while?head:
          ????????????if?head.val?!=?cur.val:
          ????????????????cur.next?=?cur?=?head
          ????????????head?=?cur.next?=?head.next
          ????????return?root

          LeetCode 第 876題:鏈表的中間結(jié)點(重要)

          #?輸入:[1,2,3,4,5]
          #輸出:此列表中的結(jié)點 3 (序列化形式:[3,4,5])
          #返回的結(jié)點值為 3 。?(測評系統(tǒng)對該結(jié)點序列化表述是?[3,4,5])。
          #注意,我們返回了一個 ListNode 類型的對象 ans,這樣:
          #ans.val?=?3,?ans.next.val?=?4,?ans.next.next.val?=?5,?以及?ans.next.next.next?=?NULL.
          #?示例 2:?
          #?輸入:[1,2,3,4,5,6]
          #輸出:此列表中的結(jié)點 4 (序列化形式:[4,5,6])
          #由于該列表有兩個中間結(jié)點,值分別為 3 和 4,我們返回第二個結(jié)點。
          #?提示:?
          #?給定鏈表的結(jié)點數(shù)介于 1 和 100?之間。?
          #?Related?Topics?鏈表

          「尋找鏈表的中間結(jié)點」

          • 遍歷兩次。第一次遍歷求導鏈表長度,找出中間結(jié)點的長度值,第二層遍歷找到中間結(jié)點并返回;
          • 快慢指針法。慢指針每次走一步,快指針每次走兩步,快指針走到鏈表末尾時,慢指針剛好走到鏈表中間。

          「方法2時間復雜度更低,只需遍歷一次。」

          #?Definition?for?singly-linked?list.
          class?ListNode:
          ????def?__init__(self,?x):
          ????????self.val?=?x
          ????????self.next?=?None

          class?Solution:
          ????def?middleNode(self,?head:?ListNode)?->?ListNode:
          ????????slow?=?head
          ????????fast?=?head
          ????????while??fast?and?fast.next:
          ????????????slow?=?slow.next
          ????????????fast?=?fast.next.next
          ????????return?slow

          eetCode 第148題:排序鏈表(重要)

          時間復雜度和常數(shù)級空間復雜度下,對鏈表進行排序。

          示例?1:
          輸入:?4->2->1->3
          輸出:?1->2->3->4
          示例?2:?
          輸入:?-1->5->3->4->0
          輸出:?-1->0->3->4->5?

          題目要求時間空間復雜度分別為,根據(jù)時間復雜度我們自然想到二分法,從而聯(lián)想到歸并排序。歸并排序,后面細聊。

          利用歸并的思想,遞歸地將當前鏈表分為兩段,然后merge,分兩段的方法是使用 fast-slow 法,用兩個指針,一個每次走兩步,一個走一步,直到快的走到了末尾,然后慢的所在位置就是中間位置,這樣就分成了兩段。

          歸并排序分為兩步,

          1.找到待排序鏈表的中間節(jié)點(使用快慢指針法,leetcode 876題)

          2.合并兩個有序鏈表(leetcode 21題),因此本題相當于結(jié)合這兩步來實現(xiàn)鏈表排序。

          #?Definition?for?singly-linked?list.
          class?ListNode:
          ????def?__init__(self,?x):
          ????????self.val?=?x
          ????????self.next?=?None
          class?Solution:
          ????def?sortList(self,?head:?ListNode)?->?ListNode:
          ????????#?if?not?head?or?not?head.next:#
          ????????if?head?==?None?or?head.next?==?None:
          ????????????return?head?
          ????????slow??=?head?#快慢指針法找到鏈表中點
          ????????fast?=?head
          ????????while?fast.next?and?fast.next.next:
          ????????????slow?=?slow.next
          ????????????fast?=?fast.next.next
          ????????right?=?slow.next
          ????????#?print(right.val)
          ????????slow.next?=?None?#這一句的原因是?需要對中點前的鏈表進行割斷處理

          ????????l1?=?self.sortList(head)#遞歸保證l1和l2為有序鏈表
          ????????l2?=?self.sortList(right)
          ????????return?self.mergeTwoLists(l1,l2)
          ???#?合并兩個有序鏈表
          ????def?mergeTwoLists(self,?l1:?ListNode,?l2:?ListNode)?->?ListNode:
          ????????if?not?l1?and?not?l2:
          ????????????return?None
          ????????if?not?l1:
          ????????????return?l2
          ????????if?not?l2:
          ????????????return?l1
          ????????head?=?head1?=?ListNode(0)
          ????????while?l1?and?l2:
          ????????????if?l1.val?<=?l2.val:
          ????????????????head.next?=?l1
          ????????????????l1?=?l1.next
          ????????????else:
          ????????????????head.next?=?l2
          ????????????????l2?=?l2.next
          ????????????head?=?head.next
          ????????if?not?l1?:?head.next?=?l2
          ????????if?not?l2?:?head.next?=?l1
          ????????return?head1.next

          下面是測試代碼

          if?__name__?==?"__main__":
          ????n1?=?ListNode(4)
          ????n2?=?ListNode(7)
          ????n3?=?ListNode(6)
          ????n4?=?ListNode(9)
          ????n5?=?ListNode(12)
          ????m=n1
          ????n1.next=n2
          ????n2.next=n3
          ????n3.next=n4
          ????n4.next=n5
          ????print('原鏈表的節(jié)點:')????
          ????while?m:
          ????????print('節(jié)點%d的值:'%(m.val),m.val)
          ????????m
          =m.next
          ????print('\n排序之后的節(jié)點:')

          ????s
          =Solution()
          ????s.sortList(n1)
          ????while?n1:
          ????????print('節(jié)點%d的值:'%(n1.val),n1.val)
          ????????n1=n1.next
          #result
          原鏈表的節(jié)點:
          節(jié)點4的值:?4
          節(jié)點7的值:?7
          節(jié)點6的值:?6
          節(jié)點9的值:?9
          節(jié)點12的值:?12

          排序之后的節(jié)點:
          節(jié)點4的值:?4
          節(jié)點6的值:?6
          節(jié)點7的值:?7
          節(jié)點9的值:?9
          節(jié)點12的值:?12

          這個鏈表排序基于歸并排序算法。首先,遍歷整個鏈表,確定鏈表中元素個數(shù),同時也可以確定鏈表的中間位置;然后從中間位置切斷鏈表(mid->key=NULL);然后遞歸地給兩個鏈表進行排序;最后,合并兩個有序鏈表,形成一個完整的有序鏈表。整個算法的時間復雜度為O(n long),空間復雜度為O(1)

          「人生最重要的不是所站的位置,而是內(nèi)心所朝的方向。只要我在每篇博文中寫得自己體會,修煉身心;在每天的不斷重復學習中,耐住寂寞,練就真功,不畏艱難,奮勇前行,不忘初心,砥礪前行,人生定會有所收獲,不留遺憾 (作者:Runsen )」

          ?

          本文已收錄 GitHub,傳送門~[1] ,里面更有大廠面試完整考點,歡迎 Star。

          ?

          Reference

          [1]

          傳送門~: https://github.com/MaoliRUNsen/runsenlearnpy100

          更多的文章

          點擊下面小程序


          - END -

          瀏覽 45
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  日韩第二页| 一级欧美性爱视频 | 五月天激情影院 | 国产精品亚洲专区在线播放麻豆 | 久久99久久99久久99人受 |