由于数组有序,可以从两头开始(绝对值大)用双指针向中间(绝对值小)逼近,只遍历一次数组,时间和空间复杂度均为O(n),p指示当前元素在新数组中的下标。
class Solution(object):
def sortedSquares(self, nums):
l = 0
r = len(nums) - 1
p = len(nums) - 1
res = [0] * len(nums)
while p >= 0:
if nums[l] ** 2 <= nums[r] ** 2:
res[p] = nums[r] ** 2
r -= 1
else:
res[p] = nums[l] ** 2
l += 1
p -= 1
return res
滑动窗口法,时间O(n)、空间O(1),l和r指针各自遍历一次数组即可。但边界条件判断易错。
以下代码是左闭右开,即子数组为[l, r)的写法:
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
n = len(nums)
l = 0
r = 0
min_len = n + 1
cur_sum = 0
while r <= n: #边界条件判断易错点1
while cur_sum >= target:
min_len = min(min_len, r - l) #边界条件判断易错点2
cur_sum -= nums[l]
l += 1
if r < n: #边界条件判断易错点3:防止下标超出范围
cur_sum += nums[r]
r += 1
return min_len if min_len <= n else 0
易错点1:若写成 while r < n,可能会在 cur_sum 刚加上 nums[-1] 时结束循环,错过对这个新的子数组的左边界更改(错过第二个while循环)。
易错点2:由于左闭右开,子数组长度为 r - l。
易错点3:由于最外层是 while r <= n,为避免下标超出范围,需多加一个判断。
以下为左闭右闭,即子数组为 [l, r]的写法,该写法更简洁、不易出错:
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
n = len(nums)
l = 0
r = 0
min_len = n + 1
cur_sum = 0
while r < n: #右边界r最大取到n-1,即nums最后一个元素下标
cur_sum += nums[r] #先在cur_sum加上右边界的值,得到新的子数组[l,r]
while cur_sum >= target: #若达到target,更新数组的左边界
min_len = min(min_len, r - l + 1) #右边也是闭合的,因此数组长度r-l+1
cur_sum -= nums[l]
l += 1
r += 1 #当cur_sum小于target,更新右边界
return min_len if min_len <= n else 0
时间、空间 O(n^2) & O(n^2)
import numpy as np
class Solution:
def generateMatrix(self, n: int):
mat = np.zeros((n, n), dtype = int)
#注意x,y虽然是直觉上的横纵坐标,但x作为列idx,是mat的第1维;y作为行idx,是mat的第0维
x = 0
y = 0
xnew = 0
ynew = 0
direct = 0
i = 1
while i <= n ** 2:
if self.valid(xnew, ynew, n) and mat[ynew][xnew] == 0: #如果未超出边界而且未访问过
x, y = xnew, ynew #是有效的新坐标,赋值给x、y
mat[y][x] = i
xnew, ynew = self.move(direct, x, y)
i += 1 #只有当坐标有效、给mat[y][x]赋值后再考虑下一个i
else:
direct = (direct + 1) % 4 #顺时针转向:右->下->左->上->右
xnew, ynew = self.move(direct, x, y)
return mat.tolist() #二维np数组转为list[list[]]
def move(self, direct: int, x: int, y: int):
if direct == 0:
return [x + 1, y]
if direct == 1:
return [x, y + 1]
if direct == 2:
return [x - 1, y]
if direct == 3:
return [x, y - 1]
def valid(self, x: int, y: int, n: int) -> bool:
if x >= 0 and x < n and y >= 0 and y < n:
return True
else:
return False
易错点1:若这样初始化二维数组,将不能独立地更改数组中的元素,因此需要使用numpy数组。
mat = [[0] * n] * n
#或者
mat = []
tmp = [0] * n
for _ in range(n): #time: O(n)
mat.append(tmp)
易错点2: move()函数得到的新坐标不一定有效,若无效需要顺时针转向再重新生成新坐标,因此横纵坐标各需要维护两个变量。
易错点3:x,y虽然是直觉上的横纵坐标(在写move函数时),但x作为列idx,是mat的第1维;y作为行idx,是mat的第0维(在用下标访问二维数组元素时)。