数组
不断更新中...
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:输入: [1,3,5,6], 2
输出: 1
示例 3:输入: [1,3,5,6], 7
输出: 4
示例 4:输入: [1,3,5,6], 0
输出: 0来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:用二分法可以定位到target所在的位置/要插入的位置。要注意边界条件的写法!!!
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
while left <= right:
middle = left + (right - left) // 2
if target > nums[middle]:
left = middle + 1
elif target < nums[middle]:
right = middle - 1
else:
return middle
if right == -1: # 区间变为[0, -1], target插入第一个位置
return 0
elif left == len(nums): # 区间变为[len(nums), len(nums) + 1], target插入末尾+1
return right + 1
else: # 区间在数组中间,且left > right, target插入中间某一位置
return right + 1
27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:用双指针,初始slow和fast的起点都是下标0,fast指针用来检测fast对应的元素是否等于val,如果等于val则fast向前一步slow不动,如果不等于val则fast和slow一起动,并且将fast对应的元素赋给slow指向的地址,以此将val后面的元素往前移动。
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
slow = 0
fast = 0
while fast < len(nums):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
else:
fast += 1
return slow
15. 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:输入:nums = []
输出:[]
示例 3:输入:nums = [0]
输出:[]
提示:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:也是采用双指针,由于题目要求的是三个数,先对nums进行排序,那么可以在外层循环中从0到size-1遍历i,在内层循环中固定i、移动left和right,其中初始化left = i + 1, right = size - 1。移动left和right有三种条件,如果三个数的和为0,则将结果添加到到result,并且left和right往中间收缩;如果三个数的和大于0,则right往前走;如果三个数的和小于0,则left往后走。考虑到不能有重复的结果,所以要在中间对nums[i]、nums[left]和nums[right]进行去重,每次指针的移动都要判断移动后指向的元素是不是等于移动前的元素,如果等于的话还要继续移动,直到遇到和前一次不一样的值为止。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
size = len(nums)
# 排序
nums.sort()
result = []
i = 0
while i < size:
left = i + 1
right = size - 1
while left < right:
if nums[i] + nums[left] + nums[right] == 0: # 如果三个数的和为0,则append到result,并且left和right往中间收缩
r = [nums[i], nums[left], nums[right]]
result.append(r)
left += 1
right -= 1
# while循环用来对nums[left]和nums[right]去重
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
elif nums[i] + nums[left] + nums[right] > 0: # 如果三个数的和大于0,则right往前走
right -= 1
else: # 如果三个数的和小于0,则left往后走
left += 1
i += 1
# while循环用来对nums[i]去重
while i < size and nums[i] == nums[i - 1]:
i += 1
return result
18. 四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:输入:nums = [], target = 0
输出:[]
提示:
0 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/4sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:和三数之和的思路是一样的,三数之和是固定一个数,通过移动查找另外两个数来判断三数之和是否等于0,而四数之和可以固定两个数, 通过移动查找另外两个数来判断三数之和是否等于target,所以在代码实现上只是比三数之和多了一层外层循环。
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
size = len(nums)
nums.sort()
result = []
i = 0
while i < size:
j = i + 1
while j < size:
left = j + 1
right = size - 1
while left < right:
if nums[i] + nums[j] + nums[left] + nums[right] == target:
result.append([nums[i], nums[j], nums[left], nums[right]])
left += 1
right -= 1
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
elif nums[i] + nums[j] + nums[left] + nums[right] < target:
left += 1
else:
right -= 1
j += 1
while j < size and nums[j] == nums[j - 1]:
j += 1
i += 1
while i < size and nums[i] == nums[i - 1]:
i += 1
return result
209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:输入:target = 4, nums = [1,4,4]
输出:1
示例 3:输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
进阶:
如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:用滑动窗口的思想,滑动窗口有一个起始位置和结束位置,如果当前滑动窗口的元素sum小于target,则结束位置+1,sum继续累加新的结束位置的元素;如果当前滑动窗口的元素sum大于target,则更新当前的最短滑动窗口长度,然后sum减去滑动窗口的起始位置的元素,然后起始位置+1。最后返回记录的最短的滑动窗口长度即可,若数组的元素加起来不能满足大于等于target的话则返回0.
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
min_size = float("inf")
left = 0
right = 0
sum = nums[0] # sum为滑动窗口的和,初始化的窗口为下标0,因此初始化的和为第0个元素
while right < len(nums):
if sum < target: # 如果sum小于target,right往后走,sum累加right的值
right += 1
if right >= len(nums): # 此处要记得判断right是否越界,越界则直接break
break
sum += nums[right]
elif sum >= target: # 如果sum大于等于target,说明当前滑动窗口符合条件,更新最小长度为当前滑动窗口的长度,然后将sum减去当前滑动窗口的第一个元素,left往后走
min_size = min(min_size, right - left + 1)
sum -= nums[left]
left += 1
return min_size if min_size != float("inf") else 0 # 如果min_size仍然是无限大的话说明该数组的元素不能满足题目的要求,返回0
59. 螺旋矩阵 II
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:输入:n = 1
输出:[[1]]
提示:
1 <= n <= 20
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/spiral-matrix-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
num = n * n
matrix = [[0] * n for _ in range(n)]
count = 1
add_num = n - 1 # 待填充的矩形的每一行(列)需要填充的元素个数
i = 0 # i是可移动的行坐标
while count <= num:
start = i # start表示待填充的区间的左边界
end = add_num + i # end表示待填充的区间的右边界,区间范围是[start, end)
j = i # j是可移动的列坐标
if add_num == 0: # 如果count<=num但是add_num为0的话,说明最后一个矩形只需填充一个元素,直接往里填充count值就可以了
matrix[i][j] = count
break
# 下面用4个while循环按上右下左的顺序填充矩阵
while j < end:
matrix[i][j] = count
count += 1
j += 1
while i < end:
matrix[i][j] = count
count += 1
i += 1
while j > start:
matrix[i][j] = count
count += 1
j -= 1
while i > start:
matrix[i][j] = count
count += 1
i -= 1
i += 1
add_num = add_num - 2
return matrix