【Lintcode】1850. Pick Apples
題目地址:
https://www.lintcode.com/problem/pick-apples/description
給定一個長 n n n的陣列 A A A,再給定兩個正整數 L L L和 K K K,要求在 A A A中找到兩個不相交的長度各自為 L L L和 K K K的子區間,使得這兩個子區間的所有數之和最大。返回這個最大和。
思路是字首和。先求出 A A A的字首和陣列 p p p,使得 p [ i ] = ∑ A [ 0 : i − 1 ] p[i]=\sum A[0:i-1] p[i]=∑A[0:i−1],再求字尾和陣列 s s s,使得 s [ i ] = ∑ A [ i : n − 1 ] s[i]=\sum A[i:n-1] s[i]=∑A[i:n−1]。接下來按照這兩個區間誰在左誰在右來分類,無論怎樣,我們可以列舉左區間的右端點,這時左區間的和可以用 p p p陣列快速算出來,然後這個和再加上右區間可能取值的最大值,當列舉完左區間之後,就得到了左右區間之和的最大值了。例如,我們先考慮左 L L L右 K K K,那麼左區間的右端點的範圍就是 [ L − 1 : n − K − 1 ] [L-1:n-K-1] [L−1:n−K−1],再算 A [ n − K : n − 1 ] A[n-K:n-1] A[n−K:n−1]的最大的長為 K K K的區間的和即可。為了快速算出 A [ n − K : n − 1 ] A[n-K:n-1] A[n−K:n−1]的最大的長為 K K K的區間的和,我們從右向左遍歷 [ L − 1 : n − K − 1 ] [L-1:n-K-1] [L−1:n−K−1],然後用一個變數存右邊剩餘部分最大的長為 K K K的區間的和。即要求: max i : n − K → L { p [ i ] − p [ i − L ] + max j : n − K → i { s [ j ] − s [ j + K ] } } \max_{i:n-K\to L} \{p[i]-p[i-L]+\max_{j:n-K\to i}\{s[j]-s[j+K]\}\} i:n−K→Lmax{p[i]−p[i−L]+j:n−K→imax{s[j]−s[j+K]}}上述技巧可以讓 max j : n − K → i { s [ j ] − s [ j + K ] } \max_{j:n-K\to i}\{s[j]-s[j+K]\} maxj:n−K→i{s[j]−s[j+K]}在 O ( 1 ) O(1) O(1)時間內算出。程式碼如下:
public class Solution {
/**
* @param A: a list of integer
* @param K: a integer
* @param L: a integer
* @return: return the maximum number of apples that they can collect.
*/
public int PickApples(int[] A, int K, int L) {
// write your code here
// 算字首和和字尾和
int[] preSum = new int[A.length + 1], sufSum = new int[A.length + 1];
for (int i = 0; i < A.length; i++) {
preSum[i + 1] = preSum[i] + A[i];
}
for (int i = A.length; i > 0; i--) {
sufSum[i - 1] = sufSum[i] + A[i - 1];
}
int res = -1;
// 先算左L右K
res = Math.max(res, calc(A, L, K, preSum, sufSum));
// 再算左K右L
res = Math.max(res, calc(A, K, L, preSum, sufSum));
return res;
}
// 算左區間長l右區間長r的情況下,最大的兩區間的總和
private int calc(int[] A, int l, int r, int[] preSum, int[] sufSum) {
int res = -1;
// i是列舉左區間的右端點的右邊一位,maxR存的是左區間右邊的可選長r的區間的最大和
for (int i = A.length - r, maxR = 0; i >= l; i--) {
maxR = Math.max(maxR, sufSum[i] - sufSum[i + r]);
res = Math.max(res, maxR + preSum[i] - preSum[i - l]);
}
return res;
}
}
時空複雜度 O ( n ) O(n) O(n)。
相關文章
- git cherry-pickGit
- [LintCode] Daily TemperaturesAI
- [LintCode] Permutation in String
- pick靶場-sql注入SQL
- git cherry-pick 教程Git
- 【Lintcode】1189. Minesweeper
- [LintCode/LeetCode] Meeting RoomsLeetCodeOOM
- Lintcode 1263. Is Subsequence
- 有關git cherry-pickGit
- [LeetCode] 528. Random Pick with WeightLeetCoderandom
- [LintCode] Binary Tree Level Order
- 【Lintcode】1615. The Result of Investment
- 【Lintcode】1218. Number Complement
- 【Lintcode】1562. Number of RestaurantsREST
- 【Lintcode】141. Sqrt(x)
- 【Lintcode】576. Split Array
- 【Lintcode】1267. Lexicographical Numbers
- 【Lintcode】1732. Snakes and Ladders
- 【Lintcode】1230. Assign CookiesCookie
- 【Lintcode】1665. Calculate Number
- 【Lintcode】1415. Residual Product
- 【Lintcode】1789. Distinguish UsernameNGUI
- 【Lintcode】318. Character Grid
- 【Lintcode】572. Music PairsAI
- 【Lintcode】1736. Throw Garbage
- 【Lintcode】1891. Travel Plan
- [LeetCode/LintCode] Largest Palindrome ProductLeetCode
- [LintCode/LeetCode] Contains Duplicate IIILeetCodeAI
- [LintCode] Check Full Binary Tree
- [LintCode/LeetCode] Remove Duplicate LettersLeetCodeREM
- [LintCode] 3Sum Smaller
- Pick和Extract的區別示例
- lintcode-514-柵欄染色
- 【Lintcode】359. Make Equilateral TriangleUI
- 【Lintcode】1484. The Most Frequent Word
- 【Lintcode】1025. Custom Sort String
- 【Lintcode】1485. Holy Grail spellAI
- 【Lintcode】1786. Pub Sub Pattern