题目一:移除元素
给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。
示例:示例
输入: nums = [3,2,2,3], val = 3
输出: 新长度 2,nums = [2,2]
解答:
def remove_element(nums, val):
i = 0 # 指针i表示当前遍历的位置
for num in nums:
if num != val:
nums[i] = num # 将不等于val的数移到数组前面
i += 1
return i # 返回新长度
题目二:旋转数组
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例:示例
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解答:
def rotate(nums, k):
k = k % len(nums) # 处理k大于数组长度的情况
nums[:] = nums[-k:] + nums[:-k] # 将数组后k个元素移到前面
题目三:螺旋矩阵
给定一个包含 m x n 个元素的矩阵,按螺旋顺序返回矩阵中的所有元素。
示例:
lua
Copy code
输入: matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出: [1,2,3,6,9,8,7,4,5]
解答:
def spiral_order(matrix):
result = []
while matrix:
result += matrix.pop(0) # 添加矩阵第一行
if matrix and matrix[0]: # 若矩阵不为空且第一列存在
for row in matrix:
result.append(row.pop()) # 添加每一行的最后一个元素
if matrix:
result += matrix.pop()[::-1] # 添加矩阵最后一行,逆序添加
if matrix and matrix[0]: # 若矩阵不为空且第一列存在
for row in matrix[::-1]:
result.append(row.pop(0)) # 添加每一行的第一个元素
return result
题目四:下一个排列
实现获取下一个排列的函数,找到给定数字序列的下一个字典序更大的排列。
示例:示例
输入: nums = [1,2,3]
输出: [1,3,2]
解答:
def next_permutation(nums):
i = len(nums) - 2
while i >= 0 and nums[i] >= nums[i + 1]: # 找到第一个降序的位置
i -= 1
if i >= 0:
j = len(nums) - 1
while nums[j] <= nums[i]: # 找到第一个比nums[i]大的数
j -= 1
nums[i], nums[j] = nums[j], nums[i] # 交换两数
nums[i + 1:] = reversed(nums[i + 1:]) # 将降序序列变为升序
题目五:螺旋矩阵 II
给你一个正整数 n,生成一个包含 1 到 n^2 所有元素,按螺旋顺序填充的 n x n 正方形矩阵。
示例:
输入: n = 3
输出: [[1,2,3],[8,9,4],[7,6,5]]
def generate_matrix(n):
# 创建一个 n x n 的矩阵,初始化为全零
matrix = [[0] * n for _ in range(n)]
num = 1 # 用来填充矩阵的数字,从1开始
left, right, top, bottom = 0, n - 1, 0, n - 1
# left, right, top, bottom 分别表示当前层的左、右、上、下边界
# 当还有数字需要填充时
while num <= n * n:
# 从左到右填充上边界
for i in range(left, right + 1):
matrix[top][i] = num
num += 1
top += 1 # 上边界下移
# 从上到下填充右边界
for i in range(top, bottom + 1):
matrix[i][right] = num
num += 1
right -= 1 # 右边界左移
# 从右到左填充下边界
for i in range(right, left - 1, -1):
matrix[bottom][i] = num
num += 1
bottom -= 1 # 下边界上移
# 从下到上填充左边界
for i in range(bottom, top - 1, -1):
matrix[i][left] = num
num += 1
left += 1 # 左边界右移
return matrix # 返回填充好的螺旋矩阵
题目一:合并区间
给出一个区间的集合,请合并所有重叠的区间。
示例:
输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠,合并它们为 [1,6]。
解答:
首先,对给定的区间列表进行排序,按照区间的起始位置从小到大排列。
创建一个空列表 merged 用来存储合并后的区间。
遍历排序后的区间列表,如果当前区间与 merged 中最后一个区间不重叠,直接将该区间加入 merged。
如果重叠,更新 merged 中最后一个区间的结束位置为当前区间结束位置与之前区间结束位置的较大值。
def merge_intervals(intervals):
intervals.sort(key=lambda x: x[0]) # 按区间起始位置排序
merged = []
for interval in intervals:
if not merged or interval[0] > merged[-1][1]:
merged.append(interval) # 如果当前区间与合并后的最后一个区间不重叠,直接加入
else:
merged[-1][1] = max(merged[-1][1], interval[1]) # 否则合并区间
return merged
题目二:最长递增子序列
给定一个无序的整数数组,找到其中最长递增子序列的长度。
示例:
输入: nums = [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长递增子序列为 [2,3,7,101],长度为 4。
解答:
创建一个与给定数组等长的列表 dp,其中 dp[i] 表示以 nums[i] 结尾的最长递增子序列长度。
初始化 dp 列表为全1,因为任何数字本身也是一个递增子序列。
遍历数组,对于每个位置 i,遍历其前面的所有位置 j,如果 nums[i] > nums[j],说明可以在递增子序列的末尾添加 nums[i],从而更新 dp[i]。
def length_of_lis(nums):
dp = [1] * len(nums) # dp[i] 表示以 nums[i] 结尾的最长递增子序列长度
for i in range(len(nums)):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1) # 如果 nums[i] > nums[j],更新 dp[i]
return max(dp) if dp else 0
假设 nums = [10, 9, 2, 5, 3, 7, 101, 18]。
初始化数组 dp,长度与 nums 相同,都初始化为1,因为任何数字本身都是一个递增子序列。
从左往右遍历数组 nums,对于每个位置 i,再从位置 0 到 i-1 遍历,找到所有比 nums[i] 小的数字,说明可以在递增子序列末尾添加 nums[i],这样可以得到一个更长的递增子序列。
对于位置 i,将 dp[i] 更新为 dp[j] + 1,其中 j 是位置 i 前面的所有位置。
返回数组 dp 中的最大值,即为最长递增子序列的长度。
在示例中,数组 dp 最终变为 [1, 1, 1, 2, 2, 3, 4, 4],最大值为 4,因此最长递增子序列的长度为 4,对应的子序列是 [2, 3, 7, 101]。
这段代码利用动态规划的思想,逐步计算以每个位置为结尾的最长递增子序列的长度,从而得到整个数组的最长递增子序列的长度。
题目三:下一个排列
实现获取下一个排列的函数,找到给定数字序列的下一个字典序更大的排列。
示例:
输入: nums = [1,2,3]
输出: [1,3,2]
解答:
从后往前找到第一个非递增的数字的索引 i。
如果 i >= 0,再次从后往前找到第一个大于 nums[i] 的数字的索引 j,交换 nums[i] 和 nums[j]。
最后,反转 nums[i+1:] 部分,使其变为升序,得到下一个排列。
def next_permutation(nums):
i = len(nums) - 2 # 从倒数第二个位置开始
while i >= 0 and nums[i] >= nums[i + 1]:
i -= 1
# 此时 i 指向的位置是第一个非递增的数字的索引
if i >= 0: # 如果找到了一个非递增的数字
j = len(nums) - 1 # 从最后一个数字开始往前找
while nums[j] <= nums[i]:
j -= 1
# 此时 j 指向第一个大于 nums[i] 的数字的索引
nums[i], nums[j] = nums[j], nums[i] # 交换 nums[i] 和 nums[j]
# 将 i 后面的部分逆序,保证后面的部分是最小的排列
nums[i + 1:] = reversed(nums[i + 1:])
假设 nums = [1, 3, 5, 4, 2]。
初始时 i 指向索引 2,即数字 5。
在第一个 while 循环中,因为 5 >= 4,所以继续往前移动 i,此时 i 指向索引 1,即数字 3。
在第二个 while 循环中,j 从最后一个数字开始往前找,找到 j 指向索引 3,即数字 4,它是第一个大于 3 的数字。
执行 nums[i], nums[j] = nums[j], nums[i],交换 3 和 4,得到 nums = [1, 4, 5, 3, 2]。
执行 nums[i + 1:] = reversed(nums[i + 1:]),将索引 2 后面的部分逆序,得到 nums = [1, 4, 2, 3, 5]。
最终,数组 nums 变为 [1, 4, 2, 3, 5],这就是按照字典序生成的 nums 的下一个排列。
这段代码的主要思想是从右往左找到第一个非递增的数字,然后再从右往左找到第一个大于它的数字进行交换,最后将交换位置后的部分逆序。这样做可以保证得到下一个字典序更大的排列。