题目:977. 有序数组的平方
给你一个按 非递减顺序
排序的整数数组 nums
,返回 每个数字的平方
组成的新数组,要求也按 非递减顺序
排序。
涉及数据结构
- 数组
我的思路
- 顺序计算每个元素平方,再对新数组进行排序
- 排序可以结合双指针的用法,但没想到是两端向中间,思路不同 直接开看算法视频
- P.S. 快速排序等排序方法照样可做
nums.sort()
解法
题目前提
- 有序数组,最大值从两边取到
双指针思路
-
每次循环内对两端值判断,取较大值
-
新数组下标由大到小更新
-
时间复杂度: O ( n ) O(n) O(n)
-
双指针
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
left = 0
right = len(nums) -1
res_nums = [float(inf)] * len(nums)
res_index = len(nums) -1
while left <= right :
if nums[left]*nums[left] > nums[right]*nums[right] :
res_nums[res_index] = nums[left]*nums[left]
res_index -= 1
left += 1
else:
res_nums[res_index] = nums[right]*nums[right]
res_index -= 1
right -= 1
return res_nums
效果、心得:
- 双指针用起来不难用,但是下标更新的方式需要多看变形题,还要多注意比较更新时出现覆盖问题(什么时候需要新建数组)
题目:209. 长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
涉及数据结构
- 数组
我的思路
- 类似双指针 外层
for
用来遍历left
,内层for
用来遍历right
- 结果:超时
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
res_len = []
for left in range(0, len(nums)):
# print('left = ', left,)
temp_sum = 0
for right in range(left, len(nums)):
# print('right = ', right)
temp_sum = sum(nums[left:right+1])
# print('temp_sum = ', temp_sum)
if temp_sum >= target:
res_len.append(right - left + 1)
break
# print ('inner loop right = ', right)
# print('res_len = ', res_len)
# print('at last res_len = ', res_len)
if len(res_len) != 0:
return min(res_len)
else:
return 0
解法
题目前提
- 正整数数组
- 两层循环会超时
滑动窗口思路
-
同样用双指针
-
不断的调节子序列的起始位置和终止位置
-
暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环完成了一个不断搜索区间的过程
-
一个循环里:
j
表示终止位置 -
关键:
如何移动起始位置i
→ 当窗口中所有元素值 ≥ target时,滑动i
-
时间复杂度: O ( n ) O(n) O(n)
-
自写超时
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
res = float(inf)
left = 0
for right in range(0, len(nums)):
while sum(nums[left:right+1]) >= target:
temp = right - left + 1 # 应该是这里多了一个sum的时间复杂度
res = min(temp, res)
left += 1
if res != float(inf):
return res
else:
return 0
- 矫正
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
res = float(inf)
left = 0
cur_sum = 0
for right in range(0, len(nums)):
cur_sum += nums[right]
while cur_sum >= target:
res = min(right - left + 1, res)
cur_sum -= nums[left]
left += 1
return res if res != float(inf) else 0
效果、心得:
- 本质还是双指针,但这种谁fast谁slow,或者left在哪right又定义在哪,需要多看变形题找感觉
题目:59. 螺旋矩阵II
给你一个正整数 n
,生成一个包含 1
到 n^2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
涉及数据结构
- 二维数组
我的思路
- 盲区,直接开看视频讲解
解法
题目前提
- 正整数数组、升序
- 方阵
模拟转圈【模拟题】
- 边界处理需要注意
- 循环不变量原则:对每条边的处理规则要统一
- 转圈数:
n
/
2
n/2
n/2,若
n
是单数,直接对nums[(n-1)/2][(n-1)/2]
赋最大值 - 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 定义起始位置,每圈改变当前的起始位置
- 过程:
- 圈数
- 每圈起始位置更新
- 每圈边界值更新
- 每圈4条边怎么for
- py语法注意:如果要使用列表创建一个二维数组,可以使用生成器来辅助实现;或者用numpy
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
nums = [[0 for i in range(n)] for j in range(n)]
cir_num = n // 2
start_x, start_y = 0, 0
offset, count = 1, 1
while cir_num :
for j in range(start_y, n - offset) :
nums[start_x][j] = count
count += 1
for i in range(start_x, n - offset) :
nums[i][n - offset] = count
count += 1
for j in range(n - offset, start_y, -1) :
nums[n - offset][j] = count
count += 1
for i in range(n - offset, start_x, -1) :
nums[i][start_y] = count
count +=1
start_x += 1; start_y += 1
offset += 1; cir_num -= 1
if n%2 == 1:
nums[(n-1)//2][(n-1)//2] = n*n
return nums
效果、心得:
- 搞懂了怎么顺时针打印方阵
- 要扩展成非方阵的场景,类似题 54. 螺旋矩阵 有空可做