LeetCode:链表(一)

本组囊括链表相关题目,难度不等。

2. Add Two Numbers

题目描述:中等

思路一:

主要难点是进位的问题,使用取模和整除来求解,具体看代码中的注释:

 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
 9 
10         # 链表, 用取模和整除来解
11         dummy = ListNode(0) # 预备哑节点/虚拟节点,但它不存储数字,初始化它和current相同。
12         current = dummy 
13         carry = 0   # 初始化进位
14         while l1 or l2:  
15             x = l1.val if l1 else 0 # 设置x为l1头节点的值,也就是个位数,如果l1节点已经到达了null,设置x为0 
16             y = l2.val if l2 else 0 # 同上
17             sum = x + y + carry 
18             carry = sum // 10  # 求进位是否为1
19             current.next = ListNode(sum%10)  # 创建一个值为sum mod 10的节点,并将current的next指向它
20             if l1:  # 防止下位为空,不为空则向前移动l1,l2的节点
21                 l1 = l1.next
22             if l2:
23                 l2 = l2.next
24             current = current.next # 同时 current的指向变为当前的新节点。
25             if carry != 0: # 判断carry是否等于1,如果等于1,在链表末尾增加一个为1的节点,这里只是个形式(防止后面没有数字了,直接进1,如果有数字会继续执行覆盖这个1),后面的sum会加一个carry为1.
26                 current.next = ListNode(1)
27         return dummy.next # 返回dummy的next,也就是个位数开始的地方
28         # 初始化的节点dummy没有存储值,最后返回dummy的next 。这样的好处是不用单独对head进行判断改变值。也就是如果一开始的 head 就是代表个位数,那么开始初始化的时候并不知道它的值是多少,所以还需要在进入循环前单独对它进行值的更正,不能像现在一样只用一个循环简洁。
29 
30         # 时间复杂度:O(max(m,n)),假设 m 和 n 分别表示 l1 和 l2 的长度,上面的算法最多重复max(m,n) 次。
31         # 空间复杂度:O(max(m,n)),新列表的长度最多为max(m,n)+1。

 

 

19. Remove Nth Node From End of List

题目描述:中等

思路一:

先计算链表长度的方法当然可行,但需要两次遍历链表;我们来考虑一下进阶所说的如何通过一遍扫描实现;

考虑使用两个指针,快慢指针都指向头节点;

(1)让快指针先前进n步,如果前进n步后head已经到达空节点,则证明原链表长度为n,删除倒数第n个节点即为删除第一个节点;

(2)如果前进n步快指针未到达空节点,则让慢指针与快指针同步前进,直到慢指针.next为空,这样的话慢指针就到达了要删除节点的前一节点处,再更改next指向即可。

 1 class Solution:
 2     def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
 3         # 删除倒数第n个节点,即索引为len-n
 4         # 考虑两个特殊位置,删除开头和结尾
 5         # 考虑不用计算链表长度的方法
 6         if not head:
 7             return 0
 8         dummy = ListNode(0) # 同样先设置一个哑节点,虚拟节点,val为None,指向第一个节点。方便最后返回本身的链表头结点
 9         headc = head 
10         dummy.next = head 
11         for i in range(n): # 让head先前进n步
12             head = head.next 
13         if not head:# 如果前进n步后head已经到达空节点,则证明原链表长度为n,删除倒数第n个节点即为删除第一个节点
14             headc = headc.next # 这样即是删除第一个节点
15             return headc 
16         # 如果前进n步head未到达空节点,则让head与headc同步前进,直到head.next为空
17         while head.next != None:
18             head = head.next
19             headc = headc.next
20         # 设链表长度为n,则这样的话headc就走了len-1-n步到达要删除节点的前一节点
21         headc.next = headc.next.next  # 此时使前一节点指向被删除节点所指向的下一节点
22         return dummy.next
23         # 时间复杂度:O(N),该算法对含有N个结点的列表进行了一次遍历。因此时间复杂度为O(N)。
24         # 空间复杂度:O(1),我们只用了常量级的额外空间。

 

21. Merge Two Sorted Lists

题目描述:简单

思路一:迭代解法

像极了合并两个有序数组。
遍历两个链表,每次返回值较低的节点;具体看代码注释:

 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, val=0, next=None):
 4 #         self.val = val
 5 #         self.next = next
 6 class Solution:
 7     def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
 8         # 解法一:迭代解法
 9         # 像极了合并两个有序数组。
10         # 遍历两个链表,每次返回值较低的节点
11         head = ListNode(0)  # 固定格式,一个头节点用于生成新链表
12         dummy = head        # 一个虚拟节点用于最后返回整个生成的链表
13         while l1 and l2:
14             if l1.val < l2.val:
15                 head.next = l1 # 记住,next指向的是下一个节点而不是下一个节点的值!否则不会形成链表
16                 head = head.next # 每次更新head指向
17                 l1 = l1.next
18             else:
19                 head.next = l2
20                 head = head.next
21                 l2 = l2.next
22         # 如果前面循环没有进行,则l1/l2其中一个为空链表,则直接返回另一个链表
23         # 如果前面循环进行了,在循环终止的时候, l1 和 l2 至多有一个是非空的。由于输入的两个链表都是有序的,所以不管哪个链表是非空的,它包含的所有元素都比前面已经合并链表中的所有元素都要大。这意味着我们只需要简单地将非空链表接在合并链表的后面,并返回合并链表即可。
24         if not l1:
25             head.next = l2
26         if not l2:
27             head.next = l1  
28         return dummy.next
29         # 时间复杂度:O(N+M),M和N分别为两个链表的长度;
30         # 空间复杂度O(1)

 

思路二:递归

暂时留坑

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