本文介绍 LeetCode 题集中,有关链表的问题。
LeetCode 其他有关链表的问题:
LeetCode 题集:链表(一)
LeetCode 题集:链表(三)
2. Add Two Numbers(两数相加)
问题描述
思路与代码
本题的思路较为简单,主要注意两点:
- 两个链表表上的数字位数可能不同,即链表长度不同
- 进位的情况,最后还可能有一次额外的进位,如:99 + 999 = 1098
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
list_res = []
s, b, c = 0, 0, 0 # sum, current bit, carrying to next bit
while l1 and l2:
s = l1.val + l2.val + c
b, c = s % 10, int(s / 10)
list_res.append(b)
l1, l2 = l1.next, l2.next
while l1:
s = l1.val + c
b, c = s % 10, int(s / 10)
list_res.append(b)
l1 = l1.next
while l2:
s = l2.val + c
b, c = s % 10, int(s / 10)
list_res.append(b)
l2 = l2.next
while c: # maybe have an extra carry bit
list_res.append(c)
c = 0
# result ListNode
i = 0
head = ListNode(val=list_res[i])
res = head
while i + 1 < len(list_res):
node = ListNode(val=list_res[i + 1])
head.next = node
head = node
i += 1
head.next = None
return res
运行效果:
445. Add Two Numbers II(两数相加 II)
问题描述
思路与代码
本题最直接的思路,是先遍历两个链表得到对应的数字,然后求和,写入结果链表。
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# sum up the number
num_1, num_2 = 0, 0
while l1:
num_1 = num_1 * 10 + l1.val
l1 = l1.next
while l2:
num_2 = num_2 * 10 + l2.val
l2 = l2.next
num = num_1 + num_2
str_num = str(num) # number to string
dummy = ListNode(val=-1)
head = dummy
for c in str_num: # each digit to node
node = ListNode(val=int(c))
head.next = node
head = head.next
res = dummy.next
return res
运行效果:
此外,官方题解给出了一种通过栈来解决本题的思路。
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
s1, s2 = [], []
while l1:
s1.append(l1.val)
l1 = l1.next
while l2:
s2.append(l2.val)
l2 = l2.next
ans = None
carry = 0
while s1 or s2 or carry != 0:
a = 0 if not s1 else s1.pop()
b = 0 if not s2 else s2.pop()
cur = a + b + carry
carry = int(cur / 10)
cur %= 10
curnode = ListNode(val=cur)
curnode.next = ans
ans = curnode
return ans
运行效果:
83. Remove Duplicates from Sorted List(删除排序链表中的重复元素)
问题描述
思路与代码
本体的思路较为简单,由于链表中的数值为有序排列,因此只需考虑每个节点的下一个节点的数值是否与当前节点相等即可。
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
res = head
while head:
while head.next and head.next.val == head.val:
head.next = head.next.next
head = head.next
return res
运行效果:
82. Remove Duplicates from Sorted List II(删除排序链表中的重复元素 II)
问题描述
思路与代码
本题为前一题的变体,区别在于需要删除所有重复值节点,包括第一次出现的节点。可以使用快慢指针的方法,快指针先行遍历,直到发现非重复值,慢指针再调整 next 指向,如此循环即可,注意处理结尾为重复值的情况。
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
dummy = ListNode(val=-1, next=head)
fast, slow = dummy.next, dummy
# edge case: no nodes
if not fast:
return fast
is_dup = False
while fast.next:
fast = fast.next # keep fast preceding slow
if slow.next.val != fast.val:
if is_dup:
is_dup = False
slow.next = fast
else:
slow = slow.next
else:
is_dup = True
# in case: tail is duplicated
if is_dup:
slow.next = None
res = dummy.next
return res
运行效果:
21. Merge Two Sorted Lists(合并两个有序链表)
问题描述
思路与代码
本题可参考本文第一题(LeetCode 2)的结构,即注意处理链表比较大小后的剩余节点情况。
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode(val=-1)
head = dummy
while l1 and l2:
if l1.val <= l2.val:
head.next = l1
head, l1 = head.next, l1.next
else:
head.next = l2
head, l2 = head.next, l2.next
while l1:
head.next = l1
head, l1 = head.next, l1.next
while l2:
head.next = l2
head, l2 = head.next, l2.next
res = dummy.next
return res
运行效果:
88. Merge Sorted Array(合并两个有序数组)
问题描述
思路与代码
本题与链表无关,只是与前一题相似,都是按大小顺序对两个数组(链表)进行合并,因此代码结构也与前一题相同。
代码如下:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
i, j, k = 0, 0, 0
nums_tmp = nums1.copy()
while i < m and j < n:
if nums_tmp[i] <= nums2[j]:
nums1[k] = nums_tmp[i]
i += 1
else:
nums1[k] = nums2[j]
j += 1
k += 1
while i < m: # nums1 remaining
nums1[k] = nums_tmp[i]
i += 1
k += 1
while j < n: # nums2 remaining
nums1[k] = nums2[j]
j += 1
k += 1
运行效果: