977.有序数组的平方
思路:
暴力法:平方后排序,时间复杂度为O(nlogn),不满足条件
双指针法:非递减顺序即从小到大的顺序,平方之后的值是按照当前数值的绝对值决定大小的,0的平方是最小的
- 有负数和正数的序列,最大值出现在两端
- 只有 >=0 值的序列,最大值出现在右端
- 只有 <=0 值的序列,最大值出现在左端
因此,从两端遍历数据,从返回数组的末尾填充数据可以满足条件
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
left = 0
right = len(nums) - 1
res = [0] * len(nums)
index = len(nums) - 1
while left <= right:
if nums[left] ** 2 <= nums[right] ** 2:
res[index] = nums[right] ** 2
right -= 1
else:
res[index] = nums[left] ** 2
left += 1
index -= 1
return res
209.长度最小的子数组元素
最开始考虑暴力的写法,小case能通过,大case超时。看了文档之后用了滑动窗口,以窗口右侧(即结束窗口)索引进行遍历,左侧窗口逐渐移动,值得学习。
注意:Python中的无限大使用float('inf')表示
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
# 暴力解法,双重循环,超时
# size = len(nums)
# res = float('inf')
# for i in range(size):
# tmp = nums[i]
# for j in range(i+1, size+1):
# if tmp >= target and j-i < res:
# res = j-i
# break
# if j == size:
# break
# tmp += nums[j]
# if tmp >= target and j - i < res:
# res = j - i
# return 0 if res > size else res
# 暴力解法,上面写的比较乱,参考文档重写一遍
size = len(nums)
res = float('inf')
for i in range(size):
cur_sum = 0
for j in range(i, size):
cur_sum += nums[j]
if cur_sum >= target:
res = min(res, j-i+1)
break
return res if res != float('inf') else 0
# 滑动窗口,很精妙的写法,没有想出来
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
# 滑动窗口
i = 0 # i为滑动窗口的左边,j为滑动窗口的右边
res = float('inf')
cur_sum = 0
# 以窗口右边索引进行遍历
for j in range(len(nums)):
cur_sum += nums[j]
while cur_sum >= target:
res = min(res, j-i+1)
cur_sum -= nums[i]
i += 1
return res if res != float('inf') else 0
59.螺旋矩阵II
看题解之前的思路
模拟螺旋矩阵的过程 i为行,j为列 比如n为4,i 0 j 0-3, j 3 i 1-3, i 3 j 2-0, j 0 i 2-1, i 1 j 1-2, j 2 i 2, i 2 j 1 这个过程的规律在哪里?看不出来
看了解题思路之后
确实是模拟的思路,但是模拟是有技巧的,需要有规律。和二分查找的区间规定是类似的,遵循区间定义为不变量
比如n为4,区间为左闭右开,可以看出每一圈能够构成一个循环。一次循环可以填充两行两列,偶数的循环次数为/2,奇数的循环次数也是/2,但是奇数需要最后处理中间的数值。
循环一:i 0 j 0-2, j 3 i 0-2, i 3 j 3-1, j 0 i 3-1 起始为0,0
循环二:i 1 j 1, j 2 i 1, i 2 j 2, j 1 i 2 起始为1,1
每一个循环内有四条边,四条边没什么联系,但是不同循环内的相同边规律相同(边界有所不同),因此每条边都可以写一个循环来实现。
注意:Python中[[0]*n]*n会把[0]*n拷贝n次,需要用 res = [[0] * n for _ in range(n)]
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
loop = n // 2 # 循环次数
# res = [[0] * n] * n # 结果值,注意考虑python特性,这种写法是错误的
res = [[0] * n for _ in range(n)]
count = 1 # 计数值
offset = 1 # 限制边界值
startx = 0 # 每次循环开始的位置
starty = 0 # 每次循环开始的位置
while loop > 0:
# 开始对每条边的过程进行模拟,考虑n为4
# 循环一:i 0 j 0-2, j 3 i 0-2, i 3 j 3-1, j 0 i 3-1 起始为0,0
# 循环二:i 1 j 1, j 2 i 1, i 2 j 2, j 1 i 2 起始为1,1
for j in range(starty, n-offset):
res[startx][j] = count
count += 1
for i in range(startx, n-offset):
res[i][n-offset] = count
count += 1
for j in range(n-offset, starty, -1):
res[n-offset][j] = count
count += 1
for i in range(n-offset, startx, -1):
res[i][starty] = count
count += 1
loop -= 1
startx += 1
starty += 1
offset += 1
if n % 2 != 0:
res[n//2][n//2] = count
return res