Day2| 977.有序陣列的平方 ,209.長度最小的子陣列 ,59.螺旋矩陣II

forrestr發表於2024-05-24

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

相關文章