413.等差數列劃分

413.等差數列劃分

題目:

如果一個數列 至少有三個元素 ,並且任意兩個相鄰元素之差相同,則稱該數列爲等差數列。

例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差數列。
給你一個整數數組 nums ,返回數組 nums 中所有爲等差數組的 子數組 個數。

子數組 是數組中的一個連續序列。

示例 1:

輸入:nums = [1,2,3,4]
輸出:3
解釋:nums 中有三個子等差數組:[1, 2, 3]、[2, 3, 4] 和 [1,2,3,4] 自身。
示例 2:

輸入:nums = [1]
輸出:0

解法一 動態規劃

動態規劃重要幾點:(1) dp[i]的定義;(2)狀態;(3)選擇;

dp[i]的定義:表示第i個元素包括第i個元素之前的所有等差數列。

狀態:選擇了這個元素,可以組成更長的等差數組。或者選擇了這個元素,不能組成更長的等差數組。

選擇:只能選擇下一個。

所以動態規劃的方程爲:

dp[i] = dp[i-1]+1 //如果能組成更長的等差數組
dp[i] = 0 //如果組不成更長的等差數組

如果能組成更長的等差數組:那麼num[i]-num[i-1] == num[i-1]-num[i-2]

否則的話不能組成。所以動態規劃方程就出來了。

需要注意的是,一般情況下,在開始動態規劃的時候,需要定義初始狀態,這道題中初始狀態都是0,所以可以直接去掉。具體看代碼提示。

image-20210810154932459

代碼

class Solution {
    public int numberOfArithmeticSlices(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        //這裏應該有初始狀態.即dp[0]=dp[1]=dp[2] = 0,可以不用羅列,具體原因:
        //在定義數組的時候,基本類型的數組初始化爲零值.int的話爲0,boolean的話是false。
        for (int i = 2; i < n; i++) {
            if (nums[i]-nums[i-1] == nums[i-1]-nums[i-2]){
                dp[i] = dp[i-1]+1;
            }else {
                dp[i] = 0;
            }
        }
        return Arrays.stream(dp).sum();
    }
}

解法二:查分+計數

leetcode的官方題解。

感覺講的太複雜了,代碼其實挺簡單的。

image-20210810161211163

public int numberOfArithmeticSlices(int[] nums) {
        int n = nums.length;
        if (n == 1) {
            return 0;
        }

        int d = nums[0] - nums[1], t = 0;
        int ans = 0;
        //因爲等差數列的長度至少爲3,所以可以從i=2開始枚舉
        for (int i = 2; i < n; i++) {
            if (nums[i-1] - nums[i] == d){
                ++t;
            }else{
                d = nums[i-1] - nums[i];
                t= 0;
            }
            ans+=t;
        }
        return ans;
    }

就是在循環數組中的每個數,多設置一個重置位,當不滿足等差定義的時候,將重置位置爲0,否則的話重置位++,每次循環把重置位和ans相加即可。

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