LeetCode:链表(三)
本组囊括链表相关题目,难度不等。
61. Rotate List
题目描述:中等
解法一:
官方题解:使用成环的思想,原链表连成环,再断开环和生成新链头和链尾即可;
首先将原链表的链头和链尾连接起来形成环,然后再n-k的节点后断开环,下一个节点n-k+1即是新的链表的链头,n-k是新链表的链尾。
上述考虑的是k<=n的情况,如果k>n呢:考虑k = (k//n) * n + k % n,将k写为两部分之和,前部分是向下取整,即是n的倍数,不对最终结果有影响,只需考虑后半部分即可。于是,我们把k统一写为k%n。
1 class Solution: 2 def rotateRight(self, head: ListNode, k: int) -> ListNode: 3 4 if not head: 5 return None 6 if not head.next: 7 return head 8 old_tail = head # old_tail往后移动了,head不会移动仍在原位置 9 n = 1 10 while old_tail.next != None: 11 old_tail = old_tail.next # 先将旧链链尾的下一个节点作为新链的链头 12 n += 1 # 表长度n 13 old_tail.next = head # 原链尾指向原链头,形成环 14 new_head = head # 这句可要可不要 15 for i in range( n - k % n - 1):# 从头走到新的链表尾来断开环 16 head = head.next 17 new_head = head.next # 找到新链表的头 18 head.next = None # 再在旧链链尾断开环 19 return new_head 20 # 时间复杂度:O(N),先遍历一遍找链尾,在走n-k-1步。 21 # 空间复杂度:O(1)
86. Partition List
题目描述:中等
解法一:
对于这个道题来说,比较直观的想法是将原链表的值分为两组(大于等于x和小于x)
分组后的两个小链表,连接起来即得到答案;
我们用两个指针来跟踪这两个链表,最后连接的时候要注意边界条件;
1 class Solution: 2 def partition(self, head: ListNode, x: int) -> ListNode: 3 before_head = ListNode(0) # 两个哑节点 4 before = before_head # 两个指针 5 after_head = ListNode(0) 6 after = after_head 7 while head: # 遍历一遍链表 8 if head.val < x: 9 before.next = head 10 before = before.next 11 else: 12 after.next = head 13 after = after.next 14 head = head.next 15 after.next = None # 这里需要手动实现断链,不然如果之前这个地方指向的下一个非空,就会形成环。 16 before.next = after_head.next # 连接两个链表 17 return before_head.next # 返回哑节点的下一个节点 18 # 时间复杂度:O(N) 19 # 空间复杂度:O(1),没有使用新的空间,原地移动链表
141. Linked List Cycle
题目描述:简单
解法一:
环的意思就是后面会不止一次碰到同一个节点;
思路就是希望通过一个类似表来记录已经走过的节点,若再次碰到这个节点,则返回true
首先想到的就是哈希表,通过哈希表来记录走过的节点;
用Python实现的话就是设置一个字典,键为走过的节点值,值设为任意数即可:
1 class Solution: 2 def hasCycle(self, head: ListNode) -> bool: 3 4 hashmap = {} 5 while head: 6 if head in hashmap: 7 return True 8 else: 9 hashmap[head] = 1 10 head = head.next 11 return False 12 # 时间复杂度O(N),空间复杂度O(N) (额外的哈希表)
解法二:
进阶,在O(1)空间中解决: 使用双指针法,这里用快慢指针赛跑。
思路是什么呢,假设两个快慢指针在环形赛道上赛跑,快指针每次能跑两步而满指针每次能跑一步,这样下去,设环形长度为K,则快指针经过K次循环必定与满指针相遇;若快指针先跑到了尾部节点,则证明没有环形跑道。
1 class Solution: 2 def hasCycle(self, head: ListNode) -> bool: 3 if head == None or head.next == None: 4 return False 5 low, fast = ListNode(0), ListNode(0) 6 low = head 7 fast = head.next 8 while fast and fast.next: # 换一种写法也可以 9 if fast == low: 10 return True 11 low = low.next 12 fast = fast.next.next 13 return False