算法记录 | Day2数组
LeetCode 977-有序数组的平方
题目描述:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
解题思路
- 该题使用双指针法。
双指针法
class Solution:
def sortedSquares(self, nums):
n = len(nums)
l = 0
r = n-1
k = n - 1
res = [0] * n
while l <= r:
if abs(nums[l]) <= abs(nums[r]):
res[k] = nums[r]**2
k -= 1
r -= 1
else:
res[k] = nums[l]**2
k -= 1
l += 1
return res
细节
- 书写过程中出现了bug,是由于判断条件写成了指针不是数组里的值,orzzzzzz
总结
因为这个数值排列一定是两边的绝对值相互比较,中间的值更小。在昨天做的题目的基础上,这道题看到第一眼就立刻直觉双指针。不同的是,27-移除元素双指针是同一个方向的,977的这道题双指针是相向而行的。
LeetCode 209-长度最小的子数和
题目描述:给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 ,并返回其长度。如果不存在符合条件的子数组,返回 0
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
解题思路
- 理解题目:题目中有两个限制,一个是连续子数和
≥ target; 另一个是这个连续子数和的最小长度。 - 正常思考解法,利用两个for循环,一个遍历起始位置,一个遍历终止位置。
- 滑动窗口解法:利用一个for循环寻找终止位置,如何确定起始位置。
滑动窗口解法
class Solution:
def minSubArrayLen(self, target, nums):
n = len(nums)
start = 0
sum = 0
res = float('inf')
for i in range(start, n):
sum = sum + nums[i]
while sum >= target:
res = min(res, i - start + 1)
sum = sum - nums[start]
start = start + 1
return 0 if res == float('inf') else res
注意:
- 当判断滑动窗口的下一个起始位置,需要用的是 while 不是 if。比如
[2,3,1,2,4,3],当出现 3+1+2+4 >= 7的时候,因为是连续,我们在这个数组里进行对第一个数字的弹出,找到最小的长度 3,再减到小于7的位置,增加右边界。 - 关于滑动窗口的起始位置,这里之所以是一个for循环,是因为for循环里的i是终止位置,起始位置是利用start来进行控制的!
难点
- 题目在什么条件限制下,可以利用滑动窗口的解法
- 滑动窗口的边界条件
- 这题可以和求最长序列的比较一下。
思考中.....
总结
思考指针的整个运动过程之后,边写代码边思考,考虑边界情况,什么时候移动左边界,以及左边界移动到什么位置还是很重要的。
LeetCode 59-螺旋矩阵Ⅱ
题目描述:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
解题思路
- 本题不涉及具体算法,属于模拟过程类的题目
- 求解关键:坚持循环不变量原则
class Solution:
def generateMatrix(self, n: int):
# 初始化要填充的正方形
matrix = [[0] * n for _ in range(n)]
left, right, up, down = 0, n - 1, 0, n - 1
number = 1 # 要填充的数字
while left < right and up < down:
# 从左到右填充上边
for x in range(left, right):
matrix[up][x] = number
number += 1
# 从上到下填充右边
for y in range(up, down):
matrix[y][right] = number
number += 1
# 从右到左填充下边
for x in range(right, left, -1):
matrix[down][x] = number
number += 1
# 从下到上填充左边
for y in range(down, up, -1):
matrix[y][left] = number
number += 1
# 缩小要填充的范围
left += 1
right -= 1
up += 1
down -= 1
# 如果阶数为奇数,额外填充一次中心
if n % 2:
matrix[n // 2][n // 2] = number
return matrix
难点
这道题关键在于模拟过程,没有想明白第一步要干什么。第一步首先需要定边界,要填充的第一个位置在什么地方,最后一个位置在什么地方。当固定好四个边界位置,left, right, up, down = 0, n - 1, 0, n - 1 画出要填充的矩阵,从左到右依次定边界循环即可,最后需要缩小范围,以及考虑阶数为奇数的情况。
总结
模拟题了解的并不多,再看到题目的时候不知何时会用到模拟(思考)
第二次写博客,发现有一个人点赞,很开心~。本次题目有些难度了,主要是之前也没接触过这些解法,还需要再次巩固的题目,否则容易遗忘。