代码随想录算法训练营第二天
977.有序数组的平方
题目链接:977.有序数组的平方
思路:双指针法
def two_pointer(nums: List[int]) -> List[int]:
"""双指针法"""
new_nums = [0] * len(nums)
hp = 0 # 头指针
rp = len(nums) - 1 # 尾指针
cnt = 0 # 元素计数
while hp <= rp:
hp_square = nums[hp] ** 2
rp_square = nums[rp] ** 2
if hp_square >= rp_square:
new_nums[-cnt-1] = hp_square
hp+=1
else:
new_nums[-cnt-1] = rp_square
rp-=1
cnt +=1
return new_nums
209.长度最小的子数组
题目链接:209.长度最小的子数组
思路:暴力解法(时间复杂度O(n^2))
def brute_force(target: int, nums: List[int]) -> int:
"""暴力解法"""
res = 10 ** 5 + 1
for i in range(len(nums)):
t_res = 0
val = 0
for j in range(i, len(nums)):
t_res += 1
val += nums[j]
if val >= target:
res = min(res, t_res)
break
if res == 10 ** 5 + 1:
res = 0
return res
思路:滑动窗口(时间复杂度O(n))
问:一开始没明白为什么复杂度是O(n)?
答:看滑动窗口,每个元素只进窗口一次,和出窗口一次,一个元素就被操作两次。
def slide_window(target: int, nums: List[int]) -> int:
"""滑动窗口"""
res = 10 ** 5 + 1
sums = 0
i = 0
for j, val in enumerate(nums):
sums += val
while(sums >= target):
res = min(res, j - i + 1)
sums -= nums[i]
i += 1
if res == 10 ** 5 + 1:
res = 0
return res
59.螺旋矩阵II
题目链接:59.螺旋矩阵II
思路:将问题分解为多个圆圈的直走一步和旋转问题。
def rotate_90(base_vector: Tuple[int, int]):
"""
旋转90°
"""
x, y = base_vector
return (y, -x)
def go_ahead(coordinate: Tuple[int, int], base_vector: Tuple[int, int]):
"""
直走1格
"""
co_x, co_y = coordinate
base_x, base_y = base_vector
return co_x + base_x, co_y + base_y
def one_layer_loop(res: List[List[int]], src: Tuple[int, int], border_length: int, start_num: int):
"""
循环一圈
"""
# 起始坐标
i, j = src
if border_length == 0:
res[-j][i] = start_num
else:
# 一开始向右走
base_vector = (1, 0)
count = 0
for num in range(start_num, start_num + (border_length + 1) ** 2 - (border_length - 1) ** 2):
res[-j][i] = num
if count == border_length:
base_vector = rotate_90(base_vector)
count = 0
i, j = go_ahead((i, j), base_vector)
count += 1
return i, j
def generate_matrix(self, n: int) -> List[List[int]]:
"""
串起来
"""
res = []
for i in range(n):
res.append([0] * n)
i, j = 0, 0
cnt = 1
while n > 0:
i, j = one_layer_loop(res, (i, j), n - 1, cnt)
i += 1
j -= 1
cnt += (n ** 2 - (n - 2) ** 2)
n -= 2
return res
总结
数组理论
数组,是一片连续的地址空间,删除元素只能依靠写入覆盖,而无法释放部分内存。
拓展问题:Python 中的 list 是基于顺序存储的线性表吗?是如何实现可存放多种数据类型、且可扩容的?
二分法
保持边界设置的方法一致,要么是“左闭右闭”要么是“左闭右开”。
双指针法
在 27. 移除元素 中,快指针用于读取,满指针用于写入;
在 977.有序数组的平方 中,两个指针分别朝不同的方向遍历;
在 209.长度最小的子数组 中,两个指针共同构成了滑动窗口;
不变量?
这个有点玄学,还没理解透。
在 704. 二分查找 中,不变量是边界设置方法;
在 977.有序数组的平方 中,不变量是朝着平方下降的方向;
在 59.螺旋矩阵II 中,不变量是前进一步和拐弯这些小步骤;
感觉,不变量是将问题分解后的产物。