zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    tf.nn.batch_normalization()函数解析(最清晰的解释)
    tf.identity()函数解析(最清晰的解释)
    Github Fork项目后如何与源主机代码保持更新同步
    nginx平滑升级、在线添加模块(tengine 动态加载模块)
    nginx平滑升级、在线添加模块(tengine 动态加载模块)
    nginx平滑升级、在线添加模块(tengine 动态加载模块)
    nginx平滑升级、在线添加模块(tengine 动态加载模块)
    使用mysqldump自动备份数据库脚本
    使用mysqldump自动备份数据库脚本
    使用mysqldump自动备份数据库脚本
  • 原文地址:https://www.cnblogs.com/Jesee/p/13952496.html
Copyright © 2011-2022 走看看