日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode Hot100 ---- 链表专题专题

發(fā)布時(shí)間:2023/12/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode Hot100 ---- 链表专题专题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

鏈表

力扣109:將有序鏈表轉(zhuǎn)化為二叉搜素樹

力扣141:環(huán)形鏈表判斷是否有環(huán)

力扣142:環(huán)形鏈表檢測入口位置

力扣143:重拍鏈表

力扣160:相交鏈表

力扣206:反轉(zhuǎn)鏈表

力扣21:合并兩個有序鏈表

力扣23:合并K和有序鏈表

力扣234:回文聯(lián)表

力扣25:K個一組反轉(zhuǎn)鏈表

力扣328:奇偶鏈表

力扣445:鏈表求和(頭對齊:尾對齊)

力扣80:刪除排序數(shù)組中的重復(fù)元素

力扣82:刪除重復(fù)元素

力扣83:刪除排序鏈表中的重復(fù)元素

力扣86:分割鏈表

劍指offer:二叉搜索樹和雙向鏈表

劍指offer22:鏈表中倒數(shù)第K個節(jié)點(diǎn)

劍指offer54:二叉搜索樹中的第K大節(jié)點(diǎn)

LRU實(shí)現(xiàn)

從尾到頭打印鏈表

鏈表相關(guān)的核心點(diǎn)

  • null/nil 異常處理
  • dummy node 啞巴節(jié)點(diǎn)
  • 快慢指針
  • 插入一個節(jié)點(diǎn)到排序鏈表
  • 從一個鏈表中移除一個節(jié)點(diǎn)
  • 翻轉(zhuǎn)鏈表
  • 合并兩個鏈表
  • 找到鏈表的中間節(jié)點(diǎn)

206. 反轉(zhuǎn)鏈表

反轉(zhuǎn)一個單鏈表。

https://zengwenqi.blog.csdn.net/article/details/116308095

思路:

迭代解法,兩個指針,一前一后遍歷過去。后一個到鏈表結(jié)尾時(shí),前一個就是反轉(zhuǎn)后鏈表的頭結(jié)點(diǎn)。注意所謂雙指針,并不是指向某個節(jié)點(diǎn),而是指針就是節(jié)點(diǎn)。

class Solution:def reverseList(self, head: ListNode) -> ListNode:if head is None:return headleft, right = None, head # 用right是便于理解,也可以直接用headwhile right:tmp = right.nextright.next = leftleft = rightright = tmpreturn left # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution:# 返回ListNodedef ReverseList(self, pHead):# write code heredummy = ListNode(0)while pHead:r = pHead.nextpHead.next = dummy.nextdummy.next = pHeadpHead = rreturn dummy.next

遞歸解法:

class Solution:def reverseList(self, head: ListNode) -> ListNode:if not head:return headdef helper(head):if not head.next:return headnewhead = self.reverseList(head.next)# 以鏈表1234為例,調(diào)用完遞歸后,整個鏈表形如1 -> 2 <- 3 <- 4,newhead為4head.next.next = head # 即2.next = 1head.next = None # 即1.next=Nonereturn newheadreturn helper(head)

reverse-linked-list-ii

反轉(zhuǎn)從位置 ?m? 到 ?n? 的鏈表。請使用一趟掃描完成反轉(zhuǎn)。

  • 思路:先找到 m 處, 再反轉(zhuǎn) n - m 次即可
class Solution:def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:if head is None:return headn -= m # number of times of reversecurr = dummy = ListNode(next=head)while m > 1: # find node at m - 1curr = curr.nextm -= 1start = curr.nextwhile n > 0: # reverse n - m timestmp = start.nextstart.next = tmp.nexttmp.next = curr.nextcurr.next = tmpn -= 1return dummy.next class Solution:def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:# 設(shè)置 dummyNode 是這一類問題的一般做法dummy_node = ListNode(-1)dummy_node.next = headpre = dummy_nodefor _ in range(left - 1):pre = pre.nextcur = pre.nextfor _ in range(right - left):next = cur.nextcur.next = next.nextnext.next = pre.nextpre.next = nextreturn dummy_node.next

234. 回文鏈表

判斷一個鏈表是否為回文鏈表。

思路:

按順序保存鏈表中的值到數(shù)組中,查看是否為回文數(shù)組。

class Solution:def isPalindrome(self, head: ListNode) -> bool:l = []while head:l.append(head.val)head = head.nextreturn l==l[::-1]

O(1) 空間復(fù)雜度的解法需要破壞原鏈表(找中點(diǎn) -> 反轉(zhuǎn)后半個list -> 判斷回文),在實(shí)際應(yīng)用中往往還需要復(fù)原(后半個list再反轉(zhuǎn)一次后拼接),操作比較復(fù)雜,這里給出更工程化的做法

class Solution:def isPalindrome(self, head: ListNode) -> bool:s = []slow = fast = headwhile fast is not None and fast.next is not None:s.append(slow.val)slow = slow.nextfast = fast.next.nextif fast is not None:slow = slow.nextwhile len(s) > 0:if slow.val != s.pop():return Falseslow = slow.nextreturn True

141. 環(huán)形鏈表

判斷鏈表中是否有環(huán)。

class Solution:def hasCycle(self, head: ListNode) -> bool:if not head or not head.next:return Falseslow = headfast = head.nextwhile fast and fast.next:if slow == fast:return Trueslow = slow.nextfast = fast.next.nextreturn False

21. 合并兩個有序鏈表

將兩個升序鏈表合并為一個新的 升序 鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所有節(jié)點(diǎn)組成的。

輸入:1->2->4, 1->3->4輸出:1->1->2->3->4->4

思路:

迭代

class Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:if not l1: return l2if not l2: return l1?if l2.val < l1.val:l1, l2 = l2,l1dummy = cur = ListNode()dummy = l1while l1 and l2:if l2.val < l1.val:l1, l2 = l2,l1cur.next = l1cur = cur.nextl1 = l1.nextif not l1: cur.next = l2elif not l2: cur.next = l1return dummy

遞歸

class Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:if not l1: return l2 # 終止條件,一個為空返回另一個if not l2: return l1if l1.val < l2.val: l1.next = self.mergeTwoLists(l1.next,l2)return l1else:l2.next = self.mergeTwoLists(l1,l2.next)return l2

160. 相交鏈表

編寫一個程序,找到兩個單鏈表相交的起始節(jié)點(diǎn)。沒有則返回None.

思路: 如果有相交點(diǎn), 兩個鏈表從相交的那個點(diǎn)開始到結(jié)尾的長度是一樣的.

class Solution:def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:def get_len(head): # 計(jì)算鏈表長度(節(jié)點(diǎn)數(shù))length = 0while head:length+=1head = head.nextreturn lengthlenA = get_len(headA)lenB = get_len(headB)if lenA>lenB: # 統(tǒng)一為A長度小于等于BheadA, headB = headB, headAlenA, lenB = lenB, lenAfor i in range(lenB - lenA):headB = headB.next # 長的鏈表先走幾步, 使兩鏈表等長,然后開始遍歷while headA:if headA==headB:return headAheadA = headA.nextheadB = headB.nextreturn

142. 環(huán)形鏈表 II

給定一個鏈表,返回鏈表開始入環(huán)的第一個節(jié)點(diǎn)。 如果鏈表無環(huán),則返回 null。

思路:

快慢指針,一個每次走一步,另一個每次走兩步,走x步后相遇,則兩指針分別走了x和2x步,且其相遇時(shí)必然在環(huán)內(nèi)某處(如果有環(huán)),且快指針比慢指針多走了環(huán)的長度,即環(huán)的長度為x。

用L表示入環(huán)之前的長度,gap表示入環(huán)到相遇點(diǎn)的長度,則有L+gap=x,即L=x-gap,如果從相遇點(diǎn)繼續(xù)走x-gap長度,正好會走到入環(huán)處。因此兩指針一個從其實(shí)處走L,另一個從相遇點(diǎn)走x-gap,正好會在入環(huán)點(diǎn)相遇,返回即可。

class Solution:def detectCycle(self, head: ListNode) -> ListNode:slow, fast = head, headwhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:fast = headcnt = 0 while fast != slow:slow = slow.nextfast = fast.nextcnt +=1return slowreturn

19. 刪除鏈表的倒數(shù)第N個節(jié)點(diǎn)

給定一個鏈表,刪除鏈表的倒數(shù)第 n 個節(jié)點(diǎn),并且返回鏈表的頭結(jié)點(diǎn)。

思路:

兩個指針一前一后,一次遍歷。

注意特例是head有可能被刪除,因此不能直接返回head,而引入dummy指向head,如果head被刪除了,dummy也會指向head的下一個。

class Solution:def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:dummy = ListNode()dummy.next = headfast = slow = dummyfor i in range(n):fast = fast.nextwhile fast.next:fast, slow = fast.next, slow.nextslow.next = slow.next.nextreturn dummy.next

2. 兩數(shù)相加

給你兩個 非空 的鏈表,表示兩個非負(fù)的整數(shù)。它們每位數(shù)字都是按照 逆序的方式存儲的,并且每個節(jié)點(diǎn)只能存儲一位數(shù)字。

請你將兩個數(shù)相加,并以相同形式返回一個表示和的鏈表。

思路:

梳理清楚所有的可能性。

# Definition for singly-linked list. # class ListNode(object): # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution(object):def addTwoNumbers(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""carry = 0res = ListNode(0)head = reswhile l1 or l2 or carry != 0:sum = carryif l1:sum += l1.vall1 = l1.nextif l2:sum += l2.vall2 = l2.nextif sum < 10:res.val = sumcarry = 0else:res.val = sum % 10carry = 1if l1 or l2 or carry != 0:res.next = ListNode(0)res = res.nextreturn head

23. 合并K個升序鏈表

給你一個鏈表數(shù)組,每個鏈表都已經(jīng)按升序排列。

請你將所有鏈表合并到一個升序鏈表中,返回合并后的鏈表。

思路:

分治法,K個鏈表,N個節(jié)點(diǎn),則時(shí)間復(fù)雜度為NlogK。

因?yàn)榉种问莾蓛珊喜?#xff0c;如16個鏈表,第一次合并為8個,第二次合并為4個,第三次2個,第四次合并結(jié)束。因此合并logK輪。每輪合并時(shí),每次比較都能得到抽出一個節(jié)點(diǎn),因此比較的次數(shù)就等于節(jié)點(diǎn)數(shù),每輪均為N。

如果是一次合并,即第一次1和2合并,之后12和3合并,之后123和4合并的話,復(fù)雜度則為N^2.

class Solution:def mergeKLists(self, lists: List[ListNode]) -> ListNode:if not lists:returnself.lists = listsreturn self.splitMerge(0,len(lists)-1)def splitMerge(self,left,right):# 不斷二分,直到每次不能再分if left==right:return self.lists[left]mid = left + (right-left)//2left_ll = self.splitMerge(left,mid)right_ll = self.splitMerge(mid+1,right)return self.merge2Lists(left_ll, right_ll)def merge2Lists(self, left_ll, right_ll):if not left_ll: return right_llif not right_ll: return left_llif left_ll.val > right_ll.val:left_ll, right_ll = right_ll, left_llleft_ll.next = self.merge2Lists(left_ll.next,right_ll)return left_ll

reorder-list

方法一:線性表

因?yàn)殒湵聿恢С窒聵?biāo)訪問,所以我們無法隨機(jī)訪問鏈表中任意位置的元素。

因此比較容易想到的一個方法是,我們利用線性表存儲該鏈表,然后利用線性表可以下標(biāo)訪問的特點(diǎn),直接按順序訪問指定元素,重建該鏈表即可。

方法二:尋找鏈表中點(diǎn) + 鏈表逆序 + 合并鏈表

注意到目標(biāo)鏈表即為將原鏈表的左半端和反轉(zhuǎn)后的右半端合并后的結(jié)果。

這樣我們的任務(wù)即可劃分為三步:

??? 找到原鏈表的中點(diǎn)(參考「876. 鏈表的中間結(jié)點(diǎn)」)。
??????? 我們可以使用快慢指針來 O(N)地找到鏈表的中間節(jié)點(diǎn)。

??? 將原鏈表的右半端反轉(zhuǎn)(參考「206. 反轉(zhuǎn)鏈表」)。
??????? 我們可以使用迭代法實(shí)現(xiàn)鏈表的反轉(zhuǎn)。

??? 將原鏈表的兩端合并。
??????? 因?yàn)閮涉湵黹L度相差不超過 1,因此直接合并即可

class Solution:def reorderList(self, head: ListNode) -> None:if not head:returnmid = self.middleNode(head)l1 = headl2 = mid.nextmid.next = Nonel2 = self.reverseList(l2)self.mergeList(l1, l2)def middleNode(self, head: ListNode) -> ListNode:slow = fast = headwhile fast.next and fast.next.next:slow = slow.nextfast = fast.next.nextreturn slowdef reverseList(self, head: ListNode) -> ListNode:prev = Nonecurr = headwhile curr:nextTemp = curr.nextcurr.next = prevprev = currcurr = nextTempreturn prevdef mergeList(self, l1: ListNode, l2: ListNode):while l1 and l2:l1_tmp = l1.nextl2_tmp = l2.nextl1.next = l2l1 = l1_tmpl2.next = l1l2 = l2_tmp

sort-list

在 ?O(n?log?n) 時(shí)間復(fù)雜度和常數(shù)級空間復(fù)雜度下,對鏈表進(jìn)行排序。

  • 思路:歸并排序,slow-fast找中點(diǎn)
# Definition for singly-linked list. # class ListNode(object): # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution:def _merge(self, l1, l2):tail = l_merge = ListNode()while l1 is not None and l2 is not None:if l1.val > l2.val:tail.next = l2l2 = l2.nextelse:tail.next = l1l1 = l1.nexttail = tail.nextif l1 is not None:tail.next = l1else:tail.next = l2return l_merge.nextdef _findmid(self, head):slow, fast = head, head.nextwhile fast is not None and fast.next is not None:fast = fast.next.nextslow = slow.nextreturn slowdef sortList(self, head):if head is None or head.next is None:return headmid = self._findmid(head)tail = mid.nextmid.next = None # break from middlereturn self._merge(self.sortList(head), self.sortList(tail))

注意點(diǎn)

  • 快慢指針 判斷 fast 及 fast.next 是否為 nil 值
  • 遞歸 mergeSort 需要斷開中間節(jié)點(diǎn)
  • 遞歸返回條件為 head 為 nil 或者 head.Next 為 nil

練習(xí)

  • remove-duplicates-from-sorted-list
  • remove-duplicates-from-sorted-list-ii
  • reverse-linked-list
  • reverse-linked-list-ii
  • merge-two-sorted-lists
  • partition-list
  • sort-list
  • reorder-list
  • linked-list-cycle
  • linked-list-cycle-ii
  • palindrome-linked-list
  • copy-list-with-random-pointer

總結(jié)

以上是生活随笔為你收集整理的LeetCode Hot100 ---- 链表专题专题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。