【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
- pick靶場-sql注入SQL
- git cherry-pick 教程Git
- HDU 5303 Delicious Apples (貪心 列舉 好題)APP
- 有關git cherry-pickGit
- Leetcode - Random Pick IndexLeetCoderandomIndex
- LeetCode-Random Pick IndexLeetCoderandomIndex
- Pick和Extract的區別示例
- Cherry-Pick | 一日一 GitGit
- OpenStack Open Source Cloud Needs To Pick Up The PaceCloud
- [LintCode] Daily TemperaturesAI
- LintCode 子樹
- LintCode-Backpack
- LintCode-HeapifyAPI
- [LeetCode] 528. Random Pick with WeightLeetCoderandom
- [LintCode] Permutation in String
- LintCode 主元素 II
- LintCode 解碼方法
- LintCode-Search for a Range
- LintCode-K Sum
- LintCode-Word SegmentationSegmentation
- LintCode-Hash FunctionFunction
- LintCode-Fast PowerAST
- Lintcode-Max Tree
- LintCode-Partition Array
- LintCode-Subarray Sum
- LintCode-Majority Number
- LintCode-A+B Problem
- LintCode-BackPack II
- LintCode-Previous Permuation
- LintCode 字串比較字串
- 微信小程式pick元件使用問題總結微信小程式元件
- LPLBan/Pick選人階段的遮罩效果遮罩
- ORA-7445(dbgrmqmqpk_query_pick_key)錯誤MQ
- 面試官:你瞭解git cherry-pick嗎?面試Git
- [LintCode] 3Sum Smaller
- 【Lintcode】572. Music PairsAI
- 【Lintcode】576. Split Array