给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [ 1->4->5, 1->3->4, 2->6 ] 将它们合并到一个有序链表中得到。 1->1->2->3->4->4->5->6
示例 2:
输入:lists = [] 输出:[]
示例 3:
输入:lists = [[]] 输出:[]
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i]
按 升序 排列lists[i].length
的总和不超过10^4
python 参考题解:
第 21 道题是 "Merge k Sorted Lists",题目描述如下: 合并 k 个已排序的链表并返回一个新的已排序的链表。
示例 1:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
以下是用 Python 给出的题解:
# 定义链表节点
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def mergeKLists(lists):
# 创建一个空栈,用于存储链表的头节点
stack = []
# 遍历每个链表,将链表的头节点添加到栈中
for head in lists:
if head:
stack.append(head)
# 初始化结果链表的头节点
dummy = ListNode(0)
current = dummy
# 遍历栈,合并链表
while stack:
# 取出栈顶的链表头节点
min_head = stack.pop(0)
# 将最小头节点连接到结果链表中
current.next = min_head
current = current.next
# 如果最小头节点的下一个节点不为空,则将下一个节点添加到栈中
if min_head.next:
stack.append(min_head.next)
# 返回结果链表的头节点
return dummy.next
# 示例
lists = [
ListNode(1, ListNode(4, ListNode(5))),
ListNode(1, ListNode(3, ListNode(4))),
ListNode(2, ListNode(6))
]
result = mergeKLists(lists)
while result:
print(result.val, end=" -> ")
result = result.next
# 输出: 1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6
解题思路和步骤:
- 创建栈:首先,我们创建一个空栈
stack
,用于存储链表的头节点。 - 遍历链表:使用一个循环遍历每个链表,将链表的头节点添加到栈中。
- 初始化结果链表:创建一个哑节点
dummy
作为结果链表的头节点,并初始化一个指针current
指向哑节点。 - 遍历栈:使用一个循环遍历栈,合并链表。
- 取出最小头节点:在循环中,我们取出栈顶的链表头节点
min_head
。 - 连接最小头节点:将最小头节点连接到结果链表中。
- 更新指针:每次连接完成后,我们将
current
指针向前移动到新连接的节点。 - 添加下一个节点:如果最小头节点的下一个节点不为空,则将下一个节点添加到栈中。
- 返回结果链表:最后,我们返回哑节点的下一个节点,即新链表的头节点。
这个算法的时间复杂度是 O(k * n),其中 k 是链表的数量,n 是链表的平均长度。空间复杂度是 O(k),因为我们使用了栈来存储链表的头节点。
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入:head = [1,2,3,4] 输出:[2,1,4,3]
示例 2:
输入:head = [] 输出:[]
示例 3:
输入:head = [1] 输出:[1]
提示:
- 链表中节点的数目在范围
[0, 100]
内 0 <= Node.val <= 100
python 参考题解:
第 22 道题是 "Swap Nodes in Pairs",题目描述如下: 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
示例 1:
输入: 1->2->3->4
输出: 2->1->4->3
以下是用 Python 给出的题解:
# 定义链表节点
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def swapPairs(head: ListNode) -> ListNode:
# 创建一个哑节点作为新链表的头节点
dummy = ListNode(0)
dummy.next = head
current = dummy
# 遍历链表,交换相邻的节点
while current.next and current.next.next:
# 保存第一个节点的下一个节点
next_node = current.next.next
# 交换第一个节点和第二个节点
current.next.next = current.next.next.next
next_node.next = current.next
current.next = next_node
# 移动到下一个交换对
current = current.next.next
# 返回新链表的头节点
return dummy.next
# 示例
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)
result = swapPairs(head)
while result:
print(result.val, end=" -> ")
result = result.next
# 输出: 2 -> 1 -> 4 -> 3
解题思路和步骤:
- 创建哑节点:首先,我们创建一个哑节点
dummy
作为新链表的头节点,并初始化一个指针current
指向哑节点。 - 遍历链表:使用一个循环遍历链表,交换相邻的节点。
- 保存下一个节点:在循环中,我们保存第一个节点的下一个节点
next_node
。 - 交换节点:交换第一个节点和第二个节点。
- 更新指针:每次交换完成后,我们将
current
指针向前移动到新交换的节点。 - 返回结果链表:最后,我们返回哑节点的下一个节点,即新链表的头节点。
这个算法的时间复杂度是 O(n),其中 n 是链表的长度,因为我们只需要遍历链表一次。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。
给你链表的头节点 head
,每 k
个节点一组进行翻转,请你返回修改后的链表。
k
是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k
的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 1:
输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5]
示例 2:
输入:head = [1,2,3,4,5], k = 3 输出:[3,2,1,4,5]
提示:
- 链表中的节点数目为
n
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶:你可以设计一个只用 O(1)
额外内存空间的算法解决此问题吗?
python 参考题解:
第 23 道题是 "Reverse Nodes in k-Group",题目描述如下: 给定一个链表和整数 k,请你对链表进行分块反转,其中每个块包含 k 个节点。
示例 1:
输入: 1->2->3->4->5, k = 2
输出: 2->1->4->3->5
以下是用 Python 给出的题解:
# 定义链表节点
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def reverseKGroup(head: ListNode, k: int) -> ListNode:
# 创建一个哑节点作为新链表的头节点
dummy = ListNode(0)
dummy.next = head
current = dummy
# 遍历链表,找到需要反转的节点
while current.next:
# 初始化前驱节点和当前节点
prev = current
curr = current.next
# 遍历 k 个节点,找到需要反转的最后一个节点
for _ in range(k):
if not curr:
# 如果 k 个节点不足以构成一个完整的块,返回
return dummy.next
curr = curr.next
# 反转当前块
for _ in range(k):
next_node = curr.next
curr.next = prev.next
prev.next = curr
curr = next_node
# 更新当前节点
current.next = prev.next
# 返回新链表的头节点
return dummy.next
# 示例
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)
head.next.next.next.next = ListNode(5)
result = reverseKGroup(head, 2)
while result:
print(result.val, end=" -> ")
result = result.next
# 输出: 2 -> 1 -> 4 -> 3 -> 5
解题思路和步骤:
- 创建哑节点:首先,我们创建一个哑节点
dummy
作为新链表的头节点,并初始化一个指针current
指向哑节点。 - 遍历链表:使用一个循环遍历链表,找到需要反转的节点。
- 初始化前驱节点和当前节点:在循环中,我们初始化前驱节点
prev
和当前节点curr
。 - 遍历 k 个节点:使用一个循环遍历 k 个节点,找到需要反转的最后一个节点。
- 反转当前块:使用一个循环反转当前块。
- 更新当前节点:每次反转完成后,我们将
current
指针向前移动到新反转的块的最后一个节点。 - 返回结果链表:最后,我们返回哑节点的下一个节点,即新链表的头节点。
这个算法的时间复杂度是 O(n),其中 n 是链表的长度,因为我们只需要遍历链表一次。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。
给定一个 n × n 的二维矩阵 matrix
表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[[7,4,1],[8,5,2],[9,6,3]]
示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]] 输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
提示:
n == matrix.length == matrix[i].length
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000
python 参考题解:
第 24 道题是 "Rotate Image",题目描述如下: 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
Given input matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
Output:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
以下是用 Python 给出的题解:
def rotate(matrix):
# 先转置矩阵
matrix[:] = map(list, zip(*matrix))
# 然后反转每一行
for i in range(len(matrix)):
matrix[i] = matrix[i][::-1]
# 示例
matrix = [
[1,2,3],
[4,5,6],
[7,8,9]
]
rotate(matrix)
for row in matrix:
print(row)
# 输出:
# [7,4,1]
# [8,5,2]
# [9,6,3]
解题思路和步骤:
- 转置矩阵:首先,我们使用 Python 的内置函数
zip
和list
来实现矩阵的转置。转置矩阵意味着将原始矩阵的行转换为列,列转换为行。 - 反转每一行:然后,我们使用 Python 的切片操作符
[::-1]
来反转每一行。这意味着从最后一个元素开始,到第一个元素结束,步长为 -1,即从右到左遍历每一行。 - 返回结果:转置和反转完成后,原始矩阵已经被旋转了 90 度,所以不需要返回任何值。
这个算法的时间复杂度是 O(n^2),其中 n 是矩阵的边长,因为我们需要遍历矩阵的每一行和每一列。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。
head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
python 参考题解:
第 206 道题是 "Reverse Linked List",题目描述如下: 反转一个单链表。
示例 1:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
以下是用 Python 给出的题解:
# 定义链表节点
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def reverseList(head: ListNode) -> ListNode:
# 初始化三个指针,pre指向None,cur指向head,nex指向cur的下一个节点
pre, cur, nex = None, head, head
# 遍历链表,进行反转
while cur:
nex = cur.next # 保存cur的下一个节点
cur.next = pre # 将cur的next指针指向pre
pre = cur # 移动pre到cur的位置
cur = nex # 移动cur到nex的位置
# 反转完成后,pre指向新的头节点
return pre
# 示例
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)
head.next.next.next.next = ListNode(5)
result = reverseList(head)
while result:
print(result.val, end=" -> ")
result = result.next
# 输出: 5 -> 4 -> 3 -> 2 -> 1 -> NULL
解题思路和步骤:
- 初始化指针:首先,我们创建三个指针
pre
、cur
和nex
。pre
初始化为None
,cur
初始化为链表的头节点head
,nex
初始化为cur
的下一个节点。 - 遍历链表:使用一个循环遍历链表,进行反转操作。
- 保存下一个节点:在循环中,我们首先保存
cur
的下一个节点nex
。 - 反转当前节点:然后,我们将
cur
的next
指针指向pre
,实现反转。 - 移动指针:接着,我们将
pre
移动到cur
的位置,将cur
移动到nex
的位置。 - 返回新头节点:遍历完成后,
pre
指向新的头节点,我们返回pre
。
这个算法的时间复杂度是 O(n),其中 n 是链表的长度,因为我们只需要遍历链表一次。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。