代码随想录算法训练营第二天 |977有序数组的平方 209 长度最小的子数组 59螺旋矩阵
题目:给你一个按 非递减顺序 排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。要求时间复杂度O(N)。
链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
begin = 0
end = len(nums)-1
end_new = len(nums)-1
nums_new = [0]*len(nums)
while begin<=end: #确保没有0出现的情况下,最小的数值会被读入
# if nums[begin]<0:
if abs(nums[begin])>=abs(nums[end]):
nums_new[end_new] = nums[begin]**2
begin=begin+1
else:
nums_new[end_new] = nums[end]**2
end=end-1
end_new = end_new-1
return nums_new
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
l, r, i = 0, len(nums)-1, len(nums)-1
res = [float('inf')] * len(nums) # 需要提前定义列表,存放结果
while l <= r:
if nums[l] ** 2 < nums[r] ** 2: # 左右边界进行对比,找出最大值
res[i] = nums[r] ** 2
r -= 1 # 右指针往左移动
else:
res[i] = nums[l] ** 2
l += 1 # 左指针往右移动
i -= 1 # 存放结果的指针需要往前平移一位
return res
链接:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html#%E6%9A%B4%E5%8A%9B%E6%8E%92%E5%BA%8F
刚开始做的时候思路不太清晰,使用左指针遇到0作为循环结束条件(此时会比上面的方法省略了正数部分的顺序比较),因此就额外添加了正数部分的顺序排列,但是这样就会导致一些特殊情况需要额外考虑,例如全为负数的话左指针会越界,可能速度会更快,但是debug和测试用例时间更长。
左右指针这类型的题目,真的极其容易出现越界以及不知道如何设定循环结束条件的问题!
题目:给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
链接:https://leetcode.cn/problems/minimum-size-subarray-sum
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
sum_num = 0
sum_list = [0]
min_num = []
for i, list in enumerate(nums):
sum_num = sum_num + list
if (sum_num >= target) & (len(min_num) == 0):
min_num.append(i)
sum_list.append(sum_num)
print(sum_list)
if len(min_num) == 0:
return 0
else:
left = 0
right = min_num[0] + 1
index = right - left
while right <= len(nums):
i = 0
while sum_list[right] - sum_list[left] > target:
i = i + 1
left = left + 1
if (i > 0) & (sum_list[right] - sum_list[left] < target):
right = right + 1
index = right - left
continue
left = left + 1
right = right + 1
index = right - left
return index
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
链接:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html#%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3
这里需要注意,由于题目要求找最小的连续数组,当第一次查找的数组index确定之后,会左指针右指针各往前平移,这里在做判定的时候需要区分=target和
其次是这个题目还有一个方法可以思维更清晰,但是没时间写了(这个方法浪费了一些时间复杂度,因为如果index(n+1)>index(n)的话其实这个index就可以放弃,但是由于这个问题中需要确保找到每个左指针所对应的第一个大于target的位置是右指针,所以无法省略这个步骤),简单记录一下思路(也是代码随想录的思路):
题目:给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
链接:https://leetcode.cn/problems/spiral-matrix-ii/
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
方法1:
采用树的思维:做一个n2大小的循环
先设定一个nxn的矩阵为0,每次寻找网格点,第一步从(0,0)出发,优先向右移动;如果右移碰到网格边界或者已被填充,开始向下移动;如果下移碰到网格边界或者已被填充,开始向左移动;如果左移碰到网格边界或者已被填充,开始向上移动;如果上移碰到网格边界或者已被填充,开始向右移动…for循环:不设定截止边界,0来判断是否被填充
但是这是一个时间复杂度O(n2)的算法,可以优化(代码随想录的方法)
方法2:
优化的思维:首先是重复操作,例如5的网格,除了外层内部是3,最后是1,而4的网格除了外层内部是1,因此可以考虑定义函数调用n, n-2, n-4直到1或者0,需要注意此时的索引需要改变;其次是在外层的时候不用使用遍历的手法,因为内部的数值都是可以计算的,例如[:,0]=[1:n],而[:,n-1]=[3n-2:2n-1],[1:(n-1),0]=[4n-4:3n-1],[1:(n-1),n-1]=[n+1:2n-2],实际上因为list无法跨行操作其实时间复杂度还是会比较高,但是行操作还是节省复杂度的。
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
matrix = [[0 for j in range(n)] for i in range(n)]
def shell(i, n_a, delta):
matrix[i][i:(n_a + i)] = list(range(1 + delta, n_a + 1 + delta, 1))
matrix[n_a + i - 1][i:(n_a + i)] = list(range(3 * n_a - 2 + delta, 2 * n_a - 2 + delta, -1))
if n_a > 2:
for j, row in enumerate(matrix[(i + 1):(n_a + i - 1)]):
row[i] = list(range(4 * n_a - 4 + delta, 3 * n_a - 2 + delta, -1))[j]
row[n_a + i - 1] = list(range(n_a + 1 + delta, 2 * n_a - 1 + delta, 1))[j]
sum = 0
i = 0
while n >= 0:
shell(i, n, sum)
n = n - 2
i = i + 1
sum = sum + 4 * n + 4
return matrix
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
链接:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC