刪除並獲得點數

冷亦蓝發表於2024-11-13

題目

給你一個整數陣列 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

相關文章