977.有序数组的平方
代码随想录:有序数组的平方
Leetcode:977.有序数组的平方
直接做题
要求时间复杂度为O(n),想过双指针,但习惯性就想到了指针同时动,又想空间复杂度能不能为O(1),想了一会没做出来,就看代码随想录了。
看文章
思路很简单,双指针不用同时动,哪个数的平方大,就存入结果数组,然后移动指针即可。空间复杂度为O(n)。
双指针
修改了一下自己的代码如下:
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
size = len(nums)
left = 0
right = size - 1
res = [0] * size
back = size - 1
while left <= right:
if (nums[left] * nums[left] > nums[right] * nums[right]):
res[back] = nums[left] * nums[left]
back -= 1
left += 1
else:
res[back] = nums[right] * nums[right]
back -= 1
right -= 1
return res
时间复杂度:O(n)
空间复杂度:O(n)
暴力求解
1. 暴力排序法
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
for i in range(len(nums)):
nums[i] *= nums[i]
nums.sort()
return nums
2. 暴力排序法+列表推导法
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
return sorted(x*x for x in nums)
时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度
空间复杂度:O(n)
209.长度最小的子数组
代码随想录:209.长度最小的子数组
Leetcode:209.长度最小的子数组
直接做题
使用滑动窗口法求解,但边界问题(或者说循环的终止条件)想了很久,即:right已经到数组末尾,但left还需继续往前滑动。
最终AC代码如下:
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left, right = 0, 0
size = len(nums)
cur = 0
cur_len = 0
res = float('inf')
flag = False
while left < size:
if cur < target and right < size:
cur += nums[right]
right += 1
cur_len += 1
else:
if cur < target:
break
flag = True
res = min(res, cur_len)
cur -= nums[left]
left += 1
cur_len -= 1
if flag:
return res
else:
return 0
看文章
暴力求解
时间复杂度:O(n^2)
空间复杂度:O(1)
通过两个for暴力搜索,在Leetcode上无法AC了。
滑动窗口
时间复杂度:O(n)
空间复杂度:O(1)
代码随想录与自己的做法差别在于,嵌套两个while,外层是right的移动,内层是left的移动。好像更好理解一点。
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
l = len(nums)
left = 0
right = 0
min_len = float('inf')
cur_sum = 0 #当前的累加值
while right < l:
cur_sum += nums[right]
while cur_sum >= s: # 当前累加值大于目标值
min_len = min(min_len, right - left + 1)
cur_sum -= nums[left]
left += 1
right += 1
return min_len if min_len != float('inf') else 0
59. 螺旋矩阵II
代码随想录:59. 螺旋矩阵II
Leetcode:59. 螺旋矩阵II
直接做题
花了约40min,想过两种思路:
- 找规律,以n=4为例,发现填充3次,每次填充3个,然后再逐次递减,最后再补上剩余的数。但发现n=3时就不是这种规律了。
- 模拟贪吃蛇,一直往前走,如果撞到边界,或者前方有非初始化的数字,就换方向。方向的可选择集是右、下、左、上,依次切换。这个似乎可行,但实际实现有问题。
最后还是没做出来。
代码随想录解法
思路:
- 一共填充 n // 2 圈。每一圈的填充都以左闭右开的思路进行处理。
- 通过offset来处理每一圈的填充个数。
- 当n为奇数时,最后填充最中间的数。
体会:感觉还是要找到一些关键的、不受n影响的思路。
具体代码如下:
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
nums = [[0] * n for _ in range(n)]
startx, starty = 0, 0 # 起始点
loop, mid = n // 2, n // 2 # 迭代次数、n为奇数时,矩阵的中心点
count = 1 # 计数
for offset in range(1, loop + 1) : # 每循环一层偏移量加1,偏移量从1开始
for i in range(starty, n - offset) : # 从左至右,左闭右开
nums[startx][i] = count
count += 1
for i in range(startx, n - offset) : # 从上至下
nums[i][n - offset] = count
count += 1
for i in range(n - offset, starty, -1) : # 从右至左
nums[n - offset][i] = count
count += 1
for i in range(n - offset, startx, -1) : # 从下至上
nums[i][starty] = count
count += 1
startx += 1 # 更新起始点
starty += 1
if n % 2 != 0 : # n为奇数时,填充中心点
nums[mid][mid] = count
return nums
时间复杂度 O(n^2): 模拟遍历二维矩阵的时间
空间复杂度 O(1)
数组总结
基本思路:
- 二分法
- 双指针法
- 滑动窗口
- 模拟行为
以往忽略的知识点小结
- 双指针、滑动窗口的灵活使用
- 模拟行为的规律归纳(可能需要经验)
个人体会
完成时间:3h。
心得:补充了更多规范化的思路,包括双指针、滑动窗口、模拟行为,但题目是无限的、思路也是无限的,不太可能记住所有规范化的思路,还是要保持通过自己思考直接求解的初心,然后再逐步引入规范化的思路,从而解决更多问题。