977.有序数组的平方
coding tips:
- 申请一个与已知数组同样大小的数组:new_nums = [float('inf')] * len(nums) 意思为:float('inf') → 创建一个无限大的浮点数; [float('inf')] → 变成一个数组;数组 * 一个大小 → 变成这个大小的一个数组。
- 平方可表示为:i ** 2。
- 初始赋值尽量写在一行。
- 三指针,两个用于nums。一个用于new_nums。(名字你们自己定)
初始思路:刚开始只能使用暴力解法做,但是这种方法不符合“需要使用时间复杂度为O(n)的方法”,因此,看了一眼文字讲解非递减顺序的数组,“平方后的最大值只有可能在两边,不可能在中间”。OMG,醍醐灌顶,写了一版:(因为不对, bug没有找到,就不放代码了,只放图 ==)
思路更新:进一步看了讲解,我发现我的思路没有问题,但是写法有问题!!1)申请一个同样大小的新数组。以前的写法会导致,在修改新数组时,就数组的值也会变,在未来解决问题时可以用new_nums = deepcopy(nums) 的方式解决,但是现在不需要哈。2)考虑的过于全面了,“等于”的情况可以归纳到“大于”或“小于”的任意一方,无需单另列出。3)每一步都要操作的步骤就可以提到判断外面(循环里面)进行【这是优化的点】。
代码:
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
left, right, j = 0, len(nums) - 1, len(nums) - 1
# new_nums = nums 这样的直接赋值,修改new_nums时也会导致nums的变动
new_nums = [float('inf')] * len(nums) # 需要提前定义列表,存放结果
while left <= right:
# a = nums[right] * nums[right]
# b = nums[left] * nums[left]
if nums[right] ** 2 > nums[left] ** 2:
new_nums[j] = nums[right] ** 2
right -= 1
else:
new_nums[j] = nums[left] ** 2
left += 1
# else:
# 此处无需额外将等于的情况单另出来,这样做会使最后指针错乱...反正这样case2没过
# new_nums[j] = a
# right -= 1
# new_nums[j] = b
# left += 1
j -= 1 # 因为都需要做此操作,所以统一放在判断外面
return new_nums
209.长度最小的子数组
coding tips:
- min_L = float('inf') # 将最小子序列最初赋值为一个最大值;
- return subL if subL != float('inf') else 0 # 当在函数中的循环体结构中不好添加返回值时,函数整体的返回值也可以根据条件输出
初始思路:1)暴力解法:一个一个看 是否有>=的,二个二个,三个三个...只能说很麻烦;2)滑窗思想,运用了双指针,一个fast,一个slow,但是slow具体怎么移动有点混乱...写成下图:
思路更新:值得肯定的是双指针的思想,有了“不够target就移动fast,多了就移动slow”的想法。在具体实现中需要加强,1)slow移动是一个连续的过程,使用if只能判断一次,不能找到最小子序列。2)fast与slow是两个分别移动的指针,因此需要两个循环!!3)因为要更新最小子序列,所以需要随时比较取最小,要学会用不影响大局观的小方法:min(A, B)。
代码:
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
# res:当前和,subL:最小子序列长度
fast, slow, res, subL, n = 0, 0, 0, float('inf'), len(nums)
while fast < n:
res += nums[fast]
while res >= target:
subL = min(subL, fast - slow + 1) # 判断当前子序列和两指针间距哪个小
res -= nums[slow] # 总和减去slow所指元素
slow += 1 # slow向前移
fast += 1
# 如果不存在子序列就返回0,如果存在就返回subL
return subL if subL != float('inf') else 0
59.螺旋矩阵II
coding tips:nums = [[0] * n for _ in range(n)] # 生成一个全是0的n*n的矩阵
初始思路:知道应该用左闭右开的区间写,但是不知道怎么画圈...以及也发现了中间会出现一个单个格子的情况,但是没有考虑到跟奇偶数相关。
思路更新:优雅真是优雅!详见代码orz
代码:
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
goal = 1
start_x, start_y = 0, 0
nums = [[0] * n for _ in range(n)] # 生成一个全是0的n*n的矩阵
offset = 1
for loop in range(1, (n // 2) + 1): # 循环几圈
print(loop)
# 从左到右
for j in range(start_y, n - offset):
nums[start_x][j] = goal
goal += 1
# 从上到下
for i in range(start_x, n - offset):
nums[i][n - offset] = goal
goal += 1
# 从右到左
for j in range(n - offset, start_y, -1):
nums[n - offset][j] = goal
goal += 1
# 从下到上
for i in range(n - offset, start_x, -1):
nums[i][start_y] = goal
goal += 1
# 换圈&边界值
start_x += 1
start_y += 1
offset += 1
# 中心赋值
if n % 2 == 1:
nums[start_x][start_y] = goal
return nums
总结
数组的题型需要注意:
- 区间问题
- 一般都能用双指针解决问题
- 数组的元素不能删除只能覆盖(c++思想)
- 根据题目设置的前提来判断应该使用哪种方法