P.S:
- 鏈表的末尾的那個的 next 指向 None
- 鏈表類的題目比較簡單,但是如果一不小心容易寫的特別複雜,需要在面試之前把複雜的鏈表題目再熟悉一下
206 反轉鏈表(字節跳動、亞馬遜在半年內面試常考)
本題參考題解
```
迭代法
def reverseList(head):
# 申請兩個節點 pre 和 cur ,pre 指向 None
pre, cur = None, head
while cur:
cur.next = pre # 然後將當前的節點指向 pre
pre = cur
cur = cur.next
return pre
迭代法簡略寫法
def reverseList(self, head: ListNode) -> ListNode:
prev, cur = None, head
while cur:
cur.next, prev, cur = prev, cur,cur.next
return prev
# 遞歸解法
def reverseList(head):
# 遞歸終止條件是當前爲空,或者下一個節點爲空
if not head or not head.next:return head
# 這裏的 cur 就是最後一個節點
cur = self.reverseList(head.next)
head.next.next = head
# 防止鏈表循環,需要將 head.next 設置爲 空
head.next =None
return cur
對於 head.next.next = head的理解
參考動畫
# 騷氣遞歸寫法
def reverseList(self,head):
if not head or not head.next: return head
curr, head.next.next, head.next = self.reverseList(head.next), head, None
return curr
24 兩兩交換鏈表中的節點(阿里巴巴、字節跳動在半年內面試常考)
# 法1:遞歸的方法
def swapPairs(self, head: ListNode) -> ListNode:
if not head or not head.next:return head
new_start = head.next.next
head, head.next = head.next, head
head.next.next = self.swapPairs(new_start)
return head
採用增加虛擬節點的辦法:
時間複雜度是 O(N),空間複雜度是 O(1)
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
# 法二: DumyNode
if not head or not head.next:return head
dumy = ListNode(0)
dumy.next = head
cur = dumy
while cur.next and cur.next.next:
first, sec = cur.next, cur.next.next
cur.next = sec
first.next = sec.next
sec.next = first
cur = cur.next.next
return dumy.next
關於 cur = dumy 的幾點理解:
這裏的意思是 用 cur 指向當前的虛擬節點
141 環形鏈表(阿里巴巴、字節跳動、騰訊在半年內面試常考)
P.S: 環形鏈表比較套路的一個解法就是快慢指針
class Solution:
def hasCycle(self, head: ListNode) -> bool:
try:
slow, fast = head, head.next
while slow is not fast:
slow, fast = slow.next, fast.next.next
return True
except:
return False
# 哈希的辦法 時間複雜度是O(N),空間複雜度是 O(N)
def detectCycle(head):
visited = set()
node = head
while not node:
if node in visited:return node
else:
visited.add(node)
node = node.next
return None
- Floyd 算法 (時間複雜度是 O(N),空間複雜度是 O(1))
- 第一步:判斷是否有環(一個跑的快的人和一個跑的慢的人,如果有環的話,肯定可以相遇)
- 第二步:如果有環的話,我們初始化兩個指針,一個指向鏈表的頭部,一個指向相遇點,然後每次向前移動一步,知道他們相遇,相遇點就是 環的入口
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
# 第一步:判斷有沒有環
try:
slow, fast = head,head.next
while fast is not slow:
slow, fast = slow.next, fast.next.next
except:
return None
# 第二步:判斷環的入口在哪裏
# 因爲 fast 是從 head.next 開始的,所以 fast 和 slow 相遇點應該是 slow.next
slow = slow.next
while head is not slow:
head, slow = head.next, slow.next
return head
25 K 個一組翻轉鏈表(字節跳動、猿輔導在半年內面試常考)
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy = jump = ListNode(0)
dummy.next = l = r = head
while True:
count = 0
# 把鏈表切分爲長度爲 k 的段
while r and count < k:
r = r.next
count += 1
# 在一個 長度爲 k 的子鏈表裏面進行交換
if count == k:
pre, cur = r, l # 設置 pre = r, cur = l
for _ in range(k):
cur.next, pre, cur = pre, cur,cur.next
jump.next, jump, l = pre, l, r # 把各個子鏈表粘起來
else:
return dummy.next