[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 any
nums[i]
and delete it to earnnums[i]
points. Afterwards, you must deleteeveryelement equal tonums[i] - 1
andeveryelement 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 }
相關題目