【面試題57-Ⅱ 和爲s的連續正數序列】
面試題57-Ⅱ:和爲s的連續正數序列:輸入一個正整數 target ,輸出所有和爲 target 的連續正整數序列(至少含有兩個數)。序列內的數字由小到大排列,不同序列按照首個數字從小到大排列。
思路一:暴力枚舉。枚舉 1 到 target 二分之一長度(因爲超過該大小一定不可能有兩個連續正整數的和等於 target),從每個起點開始向後累加,如果找了剛好滿足的序列就輸出到 res 裏。
時間複雜度:,遍歷 target 長度的二分之一,內部循環 while 最壞情況下也會遍歷 target 長度的二分之一。
空間複雜度:
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。滑動窗口的左邊界和有邊界只能向右移動,保證了滑動窗口的 時間複雜度 爲 。
代碼邏輯:
- 初始時滑動窗口左右邊界位於第一個元素,窗口大小爲 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