LeetCode 每日一題 740. 刪除並獲得點數
阿新 • 來源:網路 • 發佈:2021-05-07
740. 刪除並獲得點數
給你一個整數陣列 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
方法一:動態規劃
思路
打家劫舍 換了一個馬甲~
先假設資料量足夠,即 [1,10000] 每個數字都有。根據題意 一旦選擇了某個數字 x,x - 1 和 x + 1 都無法選擇了,若存在多個 x,是可以進行累加的。所以每個數字對應的點數是 數字 * 個數。
對於 [1,10000] 中的每個數字,我們有 選擇 或 不選擇 兩種方案,且不能選擇相鄰的數字。這就和 打家劫舍 問題一毛一樣了~。
定義狀態 dp[i] 表示遍歷到數字 i 時能獲得的最多點數。狀態轉移方程如下,其中 sum[i] 為 數字 i * i 的個數:
- 選擇數字
i的累計點數 =dp[i - 2] + sum[i] - 不選擇數字
i的累計點數 =dp[i - 1] - 即
dp[i]= max(dp[i - 2] + sum[i],dp[i - 1])
細節
- 沒有必要構建
[0, 1000]這麼大的陣列,根據陣列最大值 max 去構建 [0, max] 的陣列即可。
參考程式碼
public int deleteAndEarn(int[] nums) {
// 構建 sum 陣列,即 數字 * 個數,作為 [打家劫舍] 問題的入參
int max = Arrays.stream(nums).max().getAsInt();
int[] sum = new int[max + 1];
for (int x : nums) {
sum[x] += x;
}
return rob(sum);
}
// 打家劫舍程式碼
public int rob(int[] sum) {
int n = sum.length;
int[] dp = new int[n];
dp[0] = sum[0];
dp[1] = Math.max(sum[0], sum[1]);
for (int i = 2; i < n; i++) {
dp[i] = Math.max(dp[i - 2] + sum[i], dp[i - 1]);
}
return dp[n - 1];
}
執行結果

