題目
給你一個整數陣列 nums ,你可以對它進行一些操作。
每次操作中,選擇任意一個 nums[i] ,刪除它並獲得 nums[i] 的點數。之後,你必須刪除 所有 等於 nums[i] - 1 和 nums[i] + 1 的元素。
開始你擁有 0 個點數。返回你能透過這些操作獲得的最大點數。
示例 1:
輸入:nums = [3,4,2]
輸出:6
解釋:
刪除 4 獲得 4 個點數,因此 3 也被刪除。
之後,刪除 2 獲得 2 個點數。總共獲得 6 個點數。
示例 2:
輸入:nums = [2,2,3,3,3,4]
輸出:9
解釋:
刪除 3 獲得 3 個點數,接著要刪除兩個 2 和 4 。
之後,再次刪除 3 獲得 3 個點數,再次刪除 3 獲得 3 個點數。
總共獲得 9 個點數。
提示:
1 <= nums.length <= 2 * 104
1 <= nums[i] <= 104
方法 動態規劃
分析
- 當我選擇一個x之後,x-1和x+1被刪除(不計入積分),與打家劫舍類似,如果我取了一個,旁邊的兩個就不能在取了.
- num[i] 的值可以重複,即值x可以對應多個i值.
我們透過遍歷,尋找nums中的最大值,以此來框定動態規劃的大小.(我們將打家劫舍部分做修改,用作函式rob,函式引數numssize以此方法被計算)
1.初始狀態
將x值合併,當我們取x時,將所有x取到.
求出maxnum框定rob傳參大小.
2.轉移處理
使用rob函式進行處理
3.結束狀態
透過rob函式求出max並返回.
程式碼
int rob(int* nums, int numsSize) {
if(numsSize == 1) return nums[0];
int first = nums[0], second = fmax(nums[0], nums[1]);
for (int i = 2; i < numsSize; i++) {
int temp = second;
second = fmax(first + nums[i], second);
first = temp;
}
return second;
}
int deleteAndEarn(int* nums, int numsSize) {
int maxnum = 0;
for (int i = 0; i < numsSize; i++) {
maxnum = fmax(maxnum, nums[i]);
} //找到最大值
int sum[maxnum + 1] = {}; //框定範圍
for (int i = 0; i < numsSize; i++) {
sum[nums[i]] += nums[i]; //計算所有為nums[i]的值的總和
}
return rob(sum,maxnum+1);
}
題目連結:https://leetcode.cn/problems/delete-and-earn/?envType=study-plan-v2&envId=dynamic-programming