在一個神秘的地牢裡,有 n
位魔法師排成一列。每位魔法師都擁有某種能量,當你接觸到他們時,你會強制吸收該魔法師的能量。能量有可能是正值(表示獲得能量),也可能是負值(表示損失能量)。
你被詛咒了,當你吸收完第 i
位魔法師的能量後,你會立刻被傳送到第 i + k
位魔法師,接著重複這個過程:每次吸收完一位魔法師的能量後都跳到 i + k
的位置。
你可以從任意一位魔法師開始,但傳送的規則固定(每次加 k
的位置跳躍)。
請你回傳你能夠獲得的最大總能量。
DP, prefix sum, 固定步長的題目
想說要放雙十連假,先寫好了結果忘記發QQ就中斷了實慘嗚嗚
剛剛才發現還能發文,就乾脆把三十天發完吧!
energy
,整數 k(跳躍間隔)1 <= energy.length <= 105
1000 <= energy[i] <= 1000
1 <= k <= energy.length - 1
i
開始,每次跳 k
步:i → i+k → i+2k → ...
Input: energy = [5,2,-10,-5,1], k = 3
Output: 3
Explanation: from magician 1+4 absorbing 2 + 1 = 3.
i-k
跳到 i
)dp[i] = energy[i] + dp[i+k]
k
個位置作為可能的終點dp
energy
,在尚未抵達終點前(終止條件:i + k < n),更新以 i 為起點所得的能量值class Solution {
public:
int maximumEnergy(vector<int>& energy, int k) {
int n = energy.size();
int maxsum = INT_MIN;
// 從後往前遍歷,直接修改原陣列
for (int i = n - 1; i >= 0 ; i--) {
// 跳 k 步還能跳到下一個位置
if(i + k < n){
energy[i] += energy[i+k];
}
maxsum = max(maxsum, energy[i]);
}
return maxsum;
}
};
class Solution {
public:
int maximumEnergy(vector<int>& energy, int k) {
int n = energy.size();
int maxsum = INT_MIN;
// 只需要從後 k 個位置開始往前累加
for (int start = n - k; start < n; start++) {
int sum = 0;
// 從 start 往前跳,每次跳 k 步
for(int i = start; i >= 0; i -= k){
sum += energy[i];
maxsum = max(maxsum, sum);
}
}
return maxsum;
}
};
Example : energy = [5,2,-10,-5,1], k = 3
i=4: dp[4] = 1 (終點)
i=3: dp[3] = -5 (終點)
i=2: dp[2] = -10 (終點)
i=1: dp[1] = 2 + dp[4] = 3 ✓ 最大值
i=0: dp[0] = 5 + dp[3] = 0
643. Maximum Average Subarray I
1262. Greatest Sum Divisible by Three
2946. Matrix Similarity After Cyclic Shifts
prefix Sum(前綴和)是資料結構中常見技巧,用來快速查詢區間和。
A
,預先計算一個 prefix
陣列,使得:prefix[0] = 0
prefix[i+1] = prefix[i] + A[i]
查詢 A[l] + A[l+1] + ... + A[r]
時,可以用:
sum = prefix[r+1] - prefix[l]
這題的步長是固定跳躍間隔 k
,並不是查詢「連續」的區間和,所以:
i, i+k, i+2k...
)vector<int> dp(n);
for (int i = n - 1; i >= 0; i--) {
dp[i] = energy[i];
if (i + k < n) {
dp[i] += dp[i + k];
}
result = max(result, dp[i]);
}
ps. 部分內容經 AI 協助整理