977.有序陣列的平方
題目建議: 本題關鍵在於理解雙指標思想
題目連結:https://leetcode.cn/problems/squares-of-a-sorted-array/
文章講解:https://programmercarl.com/0977.有序陣列的平方.html
影片講解: https://www.bilibili.com/video/BV1QB4y1D7ep
思考
存在非負數,平方之後相當於是一個開口向上的拋物線,最小值在中間,透過左右兩個指標以此比較兩端的大小,逐漸逼近中間的最小值。
注意 python list的.sort和.reverse操作返回的不是改變後的list。list本身會改變。
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
# 左右指標向中間靠攏
i = 0
j = len(nums) - 1
res = []
while i <= j :
if nums[i]**2 < nums[j]**2:
res.append(nums[j]**2)
j-=1
else:
res.append(nums[i]**2)
i+=1
res.reverse()
return res
209.長度最小的子陣列
題目建議: 本題關鍵在於理解滑動視窗,這個滑動視窗看文字講解 還挺難理解的,建議大家先看影片講解。 擴充題目可以先不做。
題目連結:https://leetcode.cn/problems/minimum-size-subarray-sum/
文章講解:https://programmercarl.com/0209.長度最小的子陣列.html
影片講解:https://www.bilibili.com/video/BV1tZ4y1q7XE
思考
1個多月前刷過這道題,又快忘了,想了20分鐘才有點思路。程式碼寫起來容易出錯,尤其是if和while巢狀,什麼時候用if,什麼時候用while容易錯亂。
下面的寫法之所以長度為j-i,是因為sum_num+=nums[j]放在了while裡,滿足條件退出時,j多加了1
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
# i j 表示滑動視窗的左右邊界
# 視窗內的數之和小於target時,j++,大於target時,i++
i = 0
j = 0
sum_num = 0
min_len = 10000000000
while j < len(nums):
while (sum_num < target and j < len(nums)):
sum_num+=nums[j]
j+=1
while (sum_num >= target and i <= j):
#print(i,j)
if j-i < min_len:
min_len = j-i
sum_num-=nums[i]
i+=1
#print(sum_num)
if min_len == 10000000000:
return 0
return min_len
這個是之前的寫法。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
i = 0
j = 0
n = len(nums)
sum_num = 0
min_res = 10000000
while j < n:
sum_num+=nums[j]
if sum_num<target:
j+=1
else:
while sum_num >= target:
min_res = min(min_res,j-i+1)
sum_num = sum_num - nums[i]
i+=1
j+=1
if min_res == 10000000:
min_res = 0
return min_res
其中if sum_num<target的判斷條件可以合併在下面的while裡,精簡後的程式碼如下
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
題目建議: 本題關鍵還是在轉圈的邏輯,在二分搜尋中提到的區間定義,在這裡又用上了。
題目連結:https://leetcode.cn/problems/spiral-matrix-ii/
文章講解:https://programmercarl.com/0059.螺旋矩陣II.html
影片講解:https://www.bilibili.com/video/BV1SL4y1N7mV/
思考
跟演算法關係不大,但是很考驗邊界條件的控制。本題透過左閉右開區間定義進行實現。
注意 python二維陣列的初始化。透過l和r來定義遍歷區間。因為是左閉右開,所有控制條件是l<r。(l=r時,取不到值了),所以如果n為奇數,最後會遇到l=r,就是最中間的數,需要單獨處理一下。
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
matrix = [[0] * n for i in range(n)]
# 區間定義
l = 0
r = n-1
index = 1
while l < r:
#初始化起點
i = l
j = l
#->
while j < r:
matrix[i][j] = index
index+=1
j+=1
#↓
while i < r:
matrix[i][j] = index
index+=1
i+=1
#<-
while j > l:
matrix[i][j] = index
index+=1
j-=1
#↑
while i > l:
matrix[i][j] = index
index+=1
i-=1
# 下一圈
l+=1
r-=1
if n%2 == 1:
#中間的數
i = int(n/2)
matrix[i][i] = index
return matrix