再論遞歸和動態規劃

在上篇文章「初探動態規劃」裏面,我提到要寫好動態規劃須要先寫好遞歸,今天就再談談怎麼寫好遞歸。算法

爲何要寫好遞歸?寫遞歸符合動態規劃的原理,同時也容易被人理解。那麼該怎麼寫好這個遞歸呢?大量的實戰練習,直接上例題。數組

  1. 最大子序和
    給定一個整數數組 nums ,找到一個具備最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
題目分析

題幹給的是一個整數數組,那麼就有正有負,這點很關鍵,若是沒有負數,這道題就根本不用想,直接數組求和。bash

直接思路就是遍歷搜索,用一個變量存儲最大值,須要兩個索引,一個指向子數組的開頭,一個指向子數組的結尾,算出子數組的值和最大值比較而且決定是否更新。post

第一波思路就這麼簡單粗暴,隨後再優化。學習

public static int maxSubArray(int[] nums) {
    return solve(0, 0, nums);
}
public static int solve(int start, int end, int[] nums) {
    if (start > end) {
        // 這裏是爲了方便表示,實際不能這樣寫,若是返回加了一個負數,會直接越界變成一個超級大的正數
        return Integer.MIN_VALUE;
    }
    if (start > nums.length - 1) {
        return Integer.MIN_VALUE;
    }
    if (end > nums.length - 1) {
        return Integer.MIN_VALUE;
    }
    int total = 0;
    // 計算子數組和
    for (int i = start; i <= end; i++) {
        total += nums[i];
    }
    //end 朝後移動一位
    int b = solve(start, end + 1, nums);
    //start 朝後移動一位
    int a = solve(start + 1, end, nums);
    // 取三者最大值返回
    total = Math.max(total, a);
    total = Math.max(total, b);
    return total;
}
複製代碼

雖然這個時間複雜度不敢恭維,但思路簡單明瞭易於理解,這種算法是確定不行得,在 LeetCode 上面會超時。測試

即便加一個 dp[start][end] 的輔助空間用記憶搜索也仍是會超時,由於在 LeetCode 會給你一個超級大的數組求和,數組大到我 QQ 消息一次都發不完的那種。然而正向遞推(for)初始條件那塊,一直沒有弄好,因此不能靠這種方式經過。優化

這個時候應該想一想遞歸還能不能優化,這種方式的遞歸太簡單粗暴了,能不能換一種柔和一點的遞歸,好比一個索引的遞歸?迴歸問題自己,子數組最大的和這個問題。ui

剛纔兩個索引的方案已經被放棄了,那麼一個索引應該怎麼存儲呢?劃重點:若是當前值比以前累加的值大,那麼以前的累加值能夠直接放棄,從新開始累加。好好體會這句話,這句話就能夠把索引從兩個變成一個。spa

public static int max = 0;
public static int maxSubArray(int[] nums) {
    max = nums[nums.length - 1];
    solve(nums.length - 1, nums[nums.length - 1], nums);
    return max;
}
public static int solve(int index, int total, int[] nums) {
    if (index < 0) {
        return -100000;
    }
    // 比較當前值和以前的積累
    total = Math.max(nums[index] + solve(index - 1, total, nums), nums[index]);
    // 始終存儲最大的那個值
    max = Math.max(max, total);
    return total;
}
複製代碼

這個版本的遞歸確定仍是過不了測試,但這樣子的記憶搜索已經能夠過全部測試用例了。code

回顧整個過程,一樣一道題,不一樣的思考方式帶來的不一樣遞歸方式,雖然都能算出答案,但這個過程明顯不同,而這就是動態規劃須要學習的地方,優化,優化,再優化。

這兩篇自我感受寫得很沒有水準,我的緣由佔大部分,我對動態規劃遠遠沒有到駕輕就熟的地步,思惟出現了斷層,不成體系。

相關文章
相關標籤/搜索