977 有序数组的平方
初始思路:
- 需要新建一个空list。双指针,找到第一个非负数作为起始点,左半边为负数,右半边为非负数,用left和right指针分别向左右两边找,对比大小,平方小的先append进新list。
- 用之前的双指针思路,最左和最右往中间找,对比大小,大的先append进list,最后将list reverse,利用[::-1]
问题:
第一个思路有些复杂,边界上面有很多需要仔细思考的地方,代码可优化空间很大。
class Solution(object):
def sortedSquares(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
res = []
idx = 0
# 找到第一个非负数
while idx < len(nums) and nums[idx] < 0:
# 一定要记得idx的范围,并且要写在nums[idx]之前,否则会out of boundary
idx += 1
left = idx - 1 # left = 非负数idx - 1 作为负数部分的指针
right = idx
while left >= 0 and right <= len(nums) - 1:
left_sq = nums[left]**2
right_sq = nums[right]**2
if left_sq <= right_sq:
res.append(left_sq)
left -= 1
else:
res.append(right_sq)
right += 1
# 对单边条件剩余情况的处理
if left >= 0:
while left >= 0:
res.append(nums[left]**2)
left -= 1
if right <= len(nums) - 1:
while right <= len(nums) - 1:
res.append(nums[right]**2)
right += 1
return res
优解与优化
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
l = 0
r = len(nums)-1
res = []
while l<=r:
if abs(nums[l])<abs(nums[r]):
res.append(nums[r]**2)
r -= 1
else:
res.append(nums[l]**2)
l += 1
return res[::-1] # python list reverse complexity: O(n)
代码随想录:
Python 定义规定大小的数组:
res = [float('inf')] * len(nums)] # 需要提前定义列表,存放结果
Complexity
time: O(n)
space: O(n)
209 长度最小的子数组
初始思路:
在看到滑动窗口的提示的时候想象到了类似双指针的移动窗口,但是想到的是遍历left指针,但这样会陷入和暴力解法相同的思路。因为时间有限,没有继续深入发散,直接看了解题思路。
参考思路后:
滑动窗口:遍历right指针,限制子数组发展的长度。
class Solution(object):
def minSubArrayLen(self, target, nums):
left = 0
right = 0
min_len = len(nums) + 1
total = 0
while right < len(nums):
total += nums[right]
if total >= target:
while total >= target:
total -= nums[left]
left += 1
sublen = right - (left-1) + 1
if sublen < min_len:
min_len = sublen
right += 1
if min_len < len(nums) + 1:
return min_len
return 0
代码随想录(优解优化):
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
Complexity
time: O(n)
space: O(1)
59 螺旋矩阵II
初始思路:
先建2D list。上行从左到右,右列从上倒下,下行从右到左,左列从下到上。
第一圈每边分别顺序写入n-1个数字,进入更内一圈,写(n-1)-2个数字。
代码随想录
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
优解参考
- 方法一:从一开始填入数字,使用direction来改变方向。如果遇到边界或者非零的位置,则向右拐变换方向。
def generateMatrix(n: int) -> List[List[int]]:
matrix = [[0] * n for _ in range(n)]
num = 1
row = 0
col = 0
direction = 0
dr = [0, 1, 0, -1]
dc = [1, 0, -1, 0]
while num <= n * n:
matrix[row][col] = num
num += 1
nextRow = row + dr[direction]
nextCol = col + dc[direction]
if nextRow < 0 or nextRow >= n or nextCol < 0 or nextCol >= n or matrix[nextRow][nextCol] != 0:
direction = (direction + 1) % 4
row += dr[direction]
col += dc[direction]
return matrix
- 方法一更简洁的写法:简化优化方向控制
class Solution(object):
def generateMatrix(self, n):
A = [[0] * n for _ in range(n)]
i, j, di, dj = 0, 0, 0, 1
for k in xrange(n*n):
A[i][j] = k + 1
if A[(i+di)%n][(j+dj)%n]:
di, dj = dj, -di
i += di
j += dj
return A
Complexity:
time: O(n^2)
space: O(1) 【因为题目要求建立n^2的数组,并不是算法本身需要的】