【動態規劃】力扣413:等差數列劃分
阿新 • • 發佈:2022-04-18
如果一個數列 至少有三個元素 ,並且任意兩個相鄰元素之差相同,則稱該數列為等差數列。
例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差數列。
給你一個整數陣列 nums ,返回陣列 nums 中所有為等差陣列的 子陣列 個數。
子陣列 是陣列中的一個連續序列。
示例:
輸入:nums = [1,2,3,4]
輸出:3
解釋:nums 中有三個子等差陣列:[1, 2, 3]、[2, 3, 4] 和 [1,2,3,4] 自身。
- 雙指標
等差數列的所有的相鄰數字的差 d 是固定的。如果我們已經知道一個子陣列的前面部分不是等差數列以後,那麼後面部分就不用判斷了。
因此,對於每個起始位置,只需要向後進行一遍掃描,直到不再構成等差數列為止,此時已經沒有必要再向後掃描。
這個思路其實就是雙指標(滑動視窗) 的解法。
作者:fuxuemingzhu
連結:https://leetcode-cn.com/problems/arithmetic-slices/solution/fu-xue-ming-zhu-bao-li-shuang-zhi-zhen-d-fc1l/
- 動態規劃
定義 dp[i] 是以 A[i] 為終點的等差數列的個數。
- A[i] - A[i - 1] == A[i - 1] - A[i - 2]時,說明增加的A[i]能和前面構成等差數列,那麼 dp[i] = dp[i - 1] + 1;
- A[i] - A[i - 1] != A[i - 1] - A[i - 2]時, 說明增加的 A[i]不能和前面構成等差數列,所以dp[i] = 0。
因此初始化dp[]元素均為 0 ,要求的是整個陣列中的等差數列的數目,所以需要把 0 <= i <= len(A - 1) 的所有 dp[i] 的結果累加起來。
class Solution: def numberOfArithmeticSlices(self, nums: List[int]) -> int: n = len(nums) if n < 3: return 0 dp = [0] * n for i in range(2, n): if(nums[i] - nums[i-1] == nums[i - 1] - nums[i - 2]): dp[i] = dp[i - 1] + 1 return sum(dp)
時間複雜度:O(N);
空間複雜度:O(N)。
- 動態規劃優化
由於 dp[i] 只和 dp[i - 1] 有關,所以可以進行狀態壓縮,只用一個變數 k 來表示以 A[i] 為終點的等差數列的個數。
class Solution:
def numberOfArithmeticSlices(self, nums: List[int]) -> int:
n = len(nums)
count, ans = 0, 0 # count計數當終點為i時的等差數列數,ans為所有的
for i in range(2, n):
if(nums[i] - nums[i-1] == nums[i - 1] - nums[i - 2]):
count += 1
ans += count
else:
count = 0
return ans
時間複雜度:O(N);
空間複雜度:O(1)。