1. 程式人生 > 其它 >[LeetCode] 740. Delete and Earn

[LeetCode] 740. Delete and Earn

You are given an integer arraynums. You want to maximize the number of points you get by performing the following operation any number of times:

  • Pick anynums[i]and delete it to earnnums[i]points. Afterwards, you must deleteeveryelement equal tonums[i] - 1andeveryelement equal tonums[i] + 1.

Returnthemaximum number of pointsyou can earn by applying the above operation some number of times

.

Example 1:

Input: nums = [3,4,2]
Output: 6
Explanation: You can perform the following operations:
- Delete 4 to earn 4 points. Consequently, 3 is also deleted. nums = [2].
- Delete 2 to earn 2 points. nums = [].
You earn a total of 6 points.

Example 2:

Input: nums = [2,2,3,3,3,4]
Output: 9
Explanation: You can perform the following operations:
- Delete a 3 to earn 3 points. All 2's and 4's are also deleted. nums = [3,3].
- Delete a 3 again to earn 3 points. nums = [3].
- Delete a 3 once more to earn 3 points. nums = [].
You earn a total of 9 points.

Constraints:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 104

刪除並獲得點數。

給你一個整數陣列nums,你可以對它進行一些操作。

每次操作中,選擇任意一個nums[i],刪除它並獲得nums[i]的點數。之後,你必須刪除 所有 等於nums[i] - 1 和 nums[i] + 1的元素。

開始你擁有 0 個點數。返回你能通過這些操作獲得的最大點數。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/delete-and-earn
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

這道題很像198題 house robber,思路是動態規劃。這裡我引用一個我看到的很好的思路。根據題意,對於任何一個 nums[i] 而言,如果你選擇了它,那麼 nums[i - 1] 和 nums[i + 1] 都不能選且只能被直接刪除,這個題設很像 house robber。獲得點數的規則是如果你刪除 nums[i],那麼你獲得的點數是nums[i]。如果我們將陣列排好序從前往後處理,其實只需要考慮當前數字之前一個數字。所以我們首先用一個 count 陣列記錄一下每個數字的出現次數和出現數字的最大值。接著我們再建立一個二維的 DP 陣列,記錄每個數字選和不選的DP值。

對於當前的數字 i,

  • 如果我選擇刪除 i,我的收益是不刪除前一個數字dp[i - 1][0] 獲得的收益 + 刪除當前數字的收益 i * counts[i]
  • 如果我選擇不刪除 i,我的收益是刪除和不刪除前一個數字的收益的較大值

最後返回最後一個數字的DP值。

時間O(n)

空間O(n^2)

Java實現

 1 class Solution {
 2     public int deleteAndEarn(int[] nums) {
 3         int[] counts = new int[10001];
 4         int max = 0;
 5         for (int num : nums) {
 6             counts[num]++;
 7             max = Math.max(max, num);
 8         }
 9 
10         int[][] dp = new int[max + 1][2];
11         for (int i = 1; i <= max; i++) {
12             dp[i][1] = dp[i - 1][0] + i * counts[i];
13             dp[i][0] = Math.max(dp[i - 1][1], dp[i - 1][0]);
14         }
15         return Math.max(dp[max][0], dp[max][1]);
16     }
17 }

我這裡提供另一種做法,思路也是DP,程式碼寫的跟 house robber 很像。初始值是 first 和 second,first 是刪除第一個元素的收益(偷第一個房子的收益),second 是不刪除第一個元素刪除第二個元素的收益(不偷第一個房子但是偷第二個房子的收益)。這裡我們首先需要用一個數組 sum 記錄偷每一個房子的收益。

時間O(n)

空間O(n)

Java實現

 1 class Solution {
 2     public int deleteAndEarn(int[] nums) {
 3         int max = 0;
 4         for (int num : nums) {
 5             max = Math.max(max, num);
 6         }
 7 
 8         // sum陣列記錄的是相同元素之和,比如有4個2的話,sum[2] = 8
 9         int[] sum = new int[max + 1];
10         for (int num : nums) {
11             sum[num] += num;
12         }
13         return rob(sum);
14     }
15 
16     public int rob(int[] nums) {
17         int len = nums.length;
18         int first = nums[0];
19         int second = Math.max(nums[0], nums[1]);
20         for (int i = 2; i < len; i++) {
21             int temp = second;
22             second = Math.max(first + nums[i], second);
23             first = temp;
24         }
25         return second;
26     }
27 }

相關題目

198. House Robber

740. Delete and Earn

LeetCode 題目總結