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

 

posted @ 2020-11-10 10:28  Jesse-jia  阅读(73)  评论(0编辑  收藏  举报