【面試題57 - ii. 和為s的連續正數序列】
題目:輸入乙個正整數 target ,輸出所有和為 target 的連續正整數序列(至少含有兩個數)。
序列內的數字由小到大排列,不同序列按照首個數字從小到大排列。
題解:摘自
什麼是滑動視窗
滑動視窗可以看成陣列中框起來的乙個部分。在一些陣列類題目中,我們可以用滑動視窗來觀察可能的候選結果。當滑動視窗從陣列的左邊滑到了右邊,我們就可以從所有的候選結果中找到最優的結果。
對於這道題來說,陣列就是正整數序列。我們設滑動視窗的左邊界為 i,右邊界為 j,則滑動視窗框起來的是乙個左閉右開區間
[i,j)。注意,為了程式設計的方便,滑動視窗一般表示成乙個左閉右開區間。在一開始,i=1,j=1,滑動視窗位於序列的最左側,視窗大小為零。
滑動視窗的重要性質是:視窗的左邊界和右邊界永遠只能向右移動,而不能向左移動。這是為了保證滑動視窗的時間複雜度是
o(n)。如果左右邊界向左移動的話,這叫做「回溯」,演算法的時間複雜度就可能不止 o(n)。
在這道題中,我們關注的是滑動視窗中所有數的和。當滑動視窗的右邊界向右移動時,也就是 j = j + 1,視窗中多了乙個數字 j,視窗的和也就要加上 j。當滑動視窗的左邊界向右移動時,也就是 i = i + 1,視窗中少了乙個數字 i,視窗的和也就要減去 i。滑動視窗只有 右邊界向右移動(擴大視窗) 和 左邊界向右移動(縮小視窗) 兩個操作,所以實際上非常簡單。
如何用滑動視窗解這道題
要用滑動視窗解這道題,我們要回答兩個問題:
第乙個問題,視窗何時擴大,何時縮小?
第二個問題,滑動視窗能找到全部的解嗎?
對於第乙個問題,回答非常簡單:
當視窗的和小於 target 的時候,視窗的和需要增加,所以要擴大視窗,視窗的右邊界向右移動
當視窗的和大於 target 的時候,視窗的和需要減少,所以要縮小視窗,視窗的左邊界向右移動
當視窗的和恰好等於 target 的時候,我們需要記錄此時的結果。設此時的視窗為
以此類推,滑動視窗的左右邊界都不需要向左移動,所以這道題用滑動視窗一定可以得到所有的解。時間複雜度是
o(n)。
注:這道題當前可以用等差數列的求和公式來計算滑動視窗的和。不過我這裡沒有使用求和公式,是為了展示更通用的解題思路。實際上,把題目中的正整數序列換成任意的遞增整數序列,這個方法都可以解。
**:
class solution:
def findcontinuoussequence(self, target: int) -> list[list[int]]:
#滑動視窗,左閉右開
#視窗何時擴大,何時縮小
i = 1
j = 1
s = 0 #視窗內的和
res =
while i <= (target // 2):
if s < target:
s += j
j += 1
elif s > target:
s -= i
i += 1
elif s == target:
tmp = [c for c in range(i, j)]
s -= i
i += 1
return res
滑動視窗leetcode
給定乙個陣列 nums,有乙個大小為 k 的滑動視窗從陣列的最左側移動到陣列的最右側。你只可以看到在滑動視窗 k 內的數字。滑動視窗每次只向右移動一位。返回滑動視窗最大值。示例 輸入 nums 1,3,1,3,5,3,6,7 和 k 3輸出 3,3,5,5,6,7 解釋 滑動視窗的位置 最大值 1 ...
leetcode 滑動視窗
3.無重複字元的最長子串 給定乙個字串,請你找出其中不含有重複字元的最長子串的長度。示例 1 輸入 abcabcbb 輸出 3解釋 因為無重複字元的最長子串是 abc 所以其長度為 3。示例 2 輸入 bbbbb 輸出 1解釋 因為無重複字元的最長子串是 b 所以其長度為 1。示例 3 輸入 pww...
leetcode 滑動視窗
滑動視窗可以套用模板 如果不是 left math.max int map.get ch 1,left 而是left int map.get ch 1 當指標到了第二個a時,因為 left map.get a 1,left會後退指向到第乙個a的下乙個下標,即1,所以得到錯誤結果 map只儲存子串中的...