Leetcode刷題:劍指offer【面試題57-Ⅱ 和爲s的連續正數序列】

【面試題57-Ⅱ 和爲s的連續正數序列】

面試題57-Ⅱ:和爲s的連續正數序列:輸入一個正整數 target ,輸出所有和爲 target 的連續正整數序列(至少含有兩個數)。序列內的數字由小到大排列,不同序列按照首個數字從小到大排列。

思路一:暴力枚舉。枚舉 1 到 target 二分之一長度(因爲超過該大小一定不可能有兩個連續正整數的和等於 target),從每個起點開始向後累加,如果找了剛好滿足的序列就輸出到 res 裏。

時間複雜度O(n2)O(n^2),遍歷 target 長度的二分之一,內部循環 while 最壞情況下也會遍歷 target 長度的二分之一。
空間複雜度O(n)O(n)

class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        res = []
        top = math.ceil(target / 2)  # 遍歷上限
        for i in range(1, top):
            j, sum = i, 0
            while sum < target:  # 尋找滿足條件的組合
                sum += j
                j += 1
            if sum == target:
                res.append([k for k in range(i,j)])
        return res

思路二:滑動窗口。設滑動窗口左邊界爲 i,右邊界爲 j,窗口表示成左閉右開區間 [i, j)。初始時,i = 1,j = 1,滑動窗口位於序列最左側,窗口大小爲 0。滑動窗口的左邊界和有邊界只能向右移動,保證了滑動窗口的 時間複雜度O(n)O(n)

代碼邏輯:

  • 初始時滑動窗口左右邊界位於第一個元素,窗口大小爲 0
  • 若當前窗口大小(窗口內所有值的和)< target,則窗口右邊界向右移動一格
  • 若當前窗口大小 > target,則窗口左邊界向右移動一格
  • 若當前窗口大小 = target,則記錄此時窗口內的結果,這是一個以 i 開頭的結果序列,將窗口左邊界繼續向右移動一格,尋找以 i+1 開頭的序列
class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        i = 1 # 滑動窗口的左邊界
        j = 1 # 滑動窗口的右邊界
        sum = 0 # 滑動窗口中數字的和
        res = []

        while i <= target // 2:
            if sum < target:
                # 右邊界向右移動
                sum += j
                j += 1
            elif sum > target:
                # 左邊界向右移動
                sum -= i
                i += 1
            else:
                # 記錄結果
                arr = list(range(i, j))
                res.append(arr)
                # 左邊界向右移動
                sum -= i
                i += 1

        return res
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章