leetcode 動態規劃

2021-06-26 10:14:37 字數 2386 閱讀 3697



題目如下:給定乙個整型陣列,至少有乙個元素,請計算子陣列最大乘積是多少?子陣列必須是原陣列中連續的一串數字構成的陣列。整數可正可負。

例如:給定陣列 [2, 3, -2, 4]。經過計算,得到最大乘積為6。子陣列為[2,3]。

根據原貼的解題思路,這道題可以用動態規劃來解,但難度在**呢?負負得正,就可惡在這裡。那這個題目怎麼辦?o(n^2)麼?是否要計算儲存之前的所有狀態?不必如此,其實就多了陣列中的元素為負情況的考慮。因為負負得正,我們除了考慮當前的最大值之外,還需要考慮當前的最小值。

原因是,如果最小值是負的,而且當前是負的,那麼乘積之後是正數,很可能就大於當前最大的。

所以遍歷一遍,計算以每個元素結尾的最大值最小值,最後找到全域性的最大值。就是我們要的結果了。

根據原貼的**,我自己重新實現了一遍,如下:

class dynprog01

)).tostring());

system.out.println(new integer(solve(new int )).tostring());

system.out.println(new integer(solve(new int )).tostring());

system.out.println(new integer(solve(new int )).tostring());

system.out.println(new integer(solve(new int )).tostring());

system.out.println(new integer(solve(new int )).tostring());

}public static int solve(int array)

return result;

}private static int max3(int a, int b, int c)

public static int max2(int a, int b)

private static int min3(int a, int b, int c)

public static int min2(int a, int b)

}

**沒有經過簡化,所以把我的測試資料也都附上了。對於所有這些例子,執行下來得到的結果都是正確的。它為什麼正確呢?

上述**裡面,max2和max3函式都是相當平凡的,它們就是從兩個或三個元素中選取最大值。關鍵在於solve函式。它裡面的那個maxval、minval、tmpmax、tmpmin和result這些變數分別表示什麼。

我昨晚上思考了許久,想明白了。對於下標i來說,maxval和minval代表的是陣列從元素0到元素i-i之間,包含元素i-1的子陣列中能得到的最大乘積和最小乘積。result則代表從元素0到元素i-1之間,乘積最大的子陣列的乘積。tmpmax和tmpmin則是將maxval、minval和元素i相乘得到的臨時結果,用於後面的比較來得到新的maxval和minval。

現在需要用一下數學歸納法。假設對於n的情況,maxval和minval還有result的值都滿足了上述條件,對於n+1的情況又如何呢?現在的情況是,新增了元素n。首先,考慮maxval。maxval要麼就是元素n,要麼就是包含元素n在內的子陣列的乘積。前者的情況顯然在這裡得到了考慮,而事實上,在我們題設的整數情況下卻不會發生,因為整數的絕對值總是大於等於1,所以之前的乘積的絕對值總是大於等於1,同時考慮maxval和minval的結果就會讓新的maxval大於等於元素n。但它對於浮點數的情況是有必要的。對於包含元素n在內的子陣列的乘積的情況,maxval表示的是可能得到的最大乘積,其他子陣列的乘積已經不可能比這個更大了,如果考慮當前值為負的情況,minval就能起到作用,所以新的maxval是正確的。

同理可證新的minval是正確的。那麼result呢?需要注意result只是從元素0到元素n-1之間的最大乘積子陣列的乘積,它未必要包含元素n-1。那很簡單,它只需要從它自己和新的maxval之間取較大值即可。

這樣的動態規劃,讓我聯想起了字串查詢用的kmp演算法。因為kmp演算法也要計算最大匹配的真字首的位置,也要用到數學歸納法。下面是我當年對kmp演算法的理解和解釋:

上面說過,現在這個動態規劃演算法也適用於浮點數。我試了[2, 0.5, 3],這個演算法也是正確的。

還有,原貼中提到的一道求和題。大致是:給定乙個整型陣列,請計算加起來的和最大的子陣列的和是多少?子陣列必須是原陣列中連續的一串數字構成的陣列。整數可正可負。

這道題更簡單些,因為我們只要一路求最大和就可以了。關鍵問題是遇到負數怎麼處理。其實也一樣,用上面的maxval和result的思路。如果元素n是乙個負數,maxval加上它將讓maxval變小,但我們要求的是包含這個元素的子陣列中的最大和,所以還是必須加上它的。只要之前的maxval本身是正的就行。如果之前的maxval本身就是負的,那我們把它拋棄,只取元素n。而result則將成為和最大的子陣列,其結尾不必是元素n。

Leetcode 動態規劃

題目 原題鏈結在這裡 最長字串鏈。給乙個單詞列表,找乙個詞鏈,使得詞鏈後乙個單詞由前乙個單詞增加乙個字元得到,求最長詞鏈長度。解答 1 根據詞鏈的定義,短的單詞可以由長的單詞減去單詞中乙個字元得到。因此可以先對單詞列表,按照單詞的長度從大到小排序。2 單詞的最大長度為 16,因此可以對於每個單詞 w...

leetcode 動態規劃

題目 給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。每次只能向下或者向右移動一步。示例 輸入 1,3,1 1,5,1 4,2,1 輸出 7 解釋 因為路徑 1 3 1 1 1 的總和最小。思路 定義一維陣列dp用於記錄起始點到某一點最小距離,...

leetcode 動態規劃

3 動態規劃三要素 重疊子問題 最優子結構 狀態轉移方程 4 狀態轉移方程最難的 明確 狀態 定義 dp 陣列 函式的含義 明確 選擇 明確 base case f 0 0,f 1 1 f n f n 1 f n 2 其中 n 1.1 遞迴計算 複雜度高,指數級別 超時 時間複雜度 o 2 n cl...