diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md index 20aa20e938f4a..84adf91e26914 100644 --- a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md @@ -69,32 +69,153 @@ tags: -### 方法一 +### 方法一:排序 + 记忆化搜索 + 二分查找 + +我们可以对奖励值数组 `rewardValues` 进行排序,然后使用记忆化搜索的方法求解最大总奖励。 + +我们定义一个函数 $\text{dfs}(x)$,表示当前总奖励为 $x$ 时,能够获得的最大总奖励。那么答案为 $\text{dfs}(0)$。 + +函数 $\text{dfs}(x)$ 的执行过程如下: + +1. 二分查找数组 `rewardValues` 中第一个大于 $x$ 的元素的下标 $i$; +2. 遍历数组 `rewardValues` 中从下标 $i$ 开始的元素,对于每个元素 $v$,计算 $v + \text{dfs}(x + v)$ 的最大值。 +3. 将结果返回。 + +为了避免重复计算,我们使用记忆化数组 `f` 记录已经计算过的结果。 + +时间复杂度 $O(n \times (\log n + M))$,空间复杂度 $O(M)$。其中 $n$ 是数组 `rewardValues` 的长度,而 $M$ 是数组 `rewardValues` 中的最大值的两倍。 #### Python3 ```python - +class Solution: + def maxTotalReward(self, rewardValues: List[int]) -> int: + @cache + def dfs(x: int) -> int: + i = bisect_right(rewardValues, x) + ans = 0 + for v in rewardValues[i:]: + ans = max(ans, v + dfs(x + v)) + return ans + + rewardValues.sort() + return dfs(0) ``` #### Java ```java - +class Solution { + private int[] nums; + private Integer[] f; + + public int maxTotalReward(int[] rewardValues) { + nums = rewardValues; + Arrays.sort(nums); + int n = nums.length; + f = new Integer[nums[n - 1] << 1]; + return dfs(0); + } + + private int dfs(int x) { + if (f[x] != null) { + return f[x]; + } + int i = Arrays.binarySearch(nums, x + 1); + i = i < 0 ? -i - 1 : i; + int ans = 0; + for (; i < nums.length; ++i) { + ans = Math.max(ans, nums[i] + dfs(x + nums[i])); + } + return f[x] = ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int maxTotalReward(vector& rewardValues) { + sort(rewardValues.begin(), rewardValues.end()); + int n = rewardValues.size(); + int f[rewardValues.back() << 1]; + memset(f, -1, sizeof(f)); + function dfs = [&](int x) { + if (f[x] != -1) { + return f[x]; + } + auto it = upper_bound(rewardValues.begin(), rewardValues.end(), x); + int ans = 0; + for (; it != rewardValues.end(); ++it) { + ans = max(ans, rewardValues[it - rewardValues.begin()] + dfs(x + *it)); + } + return f[x] = ans; + }; + return dfs(0); + } +}; ``` #### Go ```go +func maxTotalReward(rewardValues []int) int { + sort.Ints(rewardValues) + n := len(rewardValues) + f := make([]int, rewardValues[n-1]<<1) + for i := range f { + f[i] = -1 + } + var dfs func(int) int + dfs = func(x int) int { + if f[x] != -1 { + return f[x] + } + i := sort.SearchInts(rewardValues, x+1) + f[x] = 0 + for _, v := range rewardValues[i:] { + f[x] = max(f[x], v+dfs(x+v)) + } + return f[x] + } + return dfs(0) +} +``` +#### TypeScript + +```ts +function maxTotalReward(rewardValues: number[]): number { + rewardValues.sort((a, b) => a - b); + const search = (x: number): number => { + let [l, r] = [0, rewardValues.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (rewardValues[mid] > x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + const f: number[] = Array(rewardValues.at(-1)! << 1).fill(-1); + const dfs = (x: number): number => { + if (f[x] !== -1) { + return f[x]; + } + let ans = 0; + for (let i = search(x); i < rewardValues.length; ++i) { + ans = Math.max(ans, rewardValues[i] + dfs(x + rewardValues[i])); + } + return (f[x] = ans); + }; + return dfs(0); +} ``` diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md index 805862e7f352c..1cb77d57fed8d 100644 --- a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md @@ -67,32 +67,153 @@ tags: -### Solution 1 +### Solution 1: Sorting + Memoization + Binary Search + +We can sort the `rewardValues` array and then use memoization to solve for the maximum total reward. + +We define a function $\text{dfs}(x)$, representing the maximum total reward that can be obtained when the current total reward is $x$. Thus, the answer is $\text{dfs}(0)$. + +The execution process of the function $\text{dfs}(x)$ is as follows: + +1. Perform a binary search in the `rewardValues` array for the index $i$ of the first element greater than $x$; +2. Iterate over the elements in the `rewardValues` array starting from index $i$, and for each element $v$, calculate the maximum value of $v + \text{dfs}(x + v)$. +3. Return the result. + +To avoid repeated calculations, we use a memoization array `f` to record the results that have already been computed. + +The time complexity is $O(n \times (\log n + M))$, and the space complexity is $O(M)$. Where $n$ is the length of the `rewardValues` array, and $M$ is twice the maximum value in the `rewardValues` array. #### Python3 ```python - +class Solution: + def maxTotalReward(self, rewardValues: List[int]) -> int: + @cache + def dfs(x: int) -> int: + i = bisect_right(rewardValues, x) + ans = 0 + for v in rewardValues[i:]: + ans = max(ans, v + dfs(x + v)) + return ans + + rewardValues.sort() + return dfs(0) ``` #### Java ```java - +class Solution { + private int[] nums; + private Integer[] f; + + public int maxTotalReward(int[] rewardValues) { + nums = rewardValues; + Arrays.sort(nums); + int n = nums.length; + f = new Integer[nums[n - 1] << 1]; + return dfs(0); + } + + private int dfs(int x) { + if (f[x] != null) { + return f[x]; + } + int i = Arrays.binarySearch(nums, x + 1); + i = i < 0 ? -i - 1 : i; + int ans = 0; + for (; i < nums.length; ++i) { + ans = Math.max(ans, nums[i] + dfs(x + nums[i])); + } + return f[x] = ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int maxTotalReward(vector& rewardValues) { + sort(rewardValues.begin(), rewardValues.end()); + int n = rewardValues.size(); + int f[rewardValues.back() << 1]; + memset(f, -1, sizeof(f)); + function dfs = [&](int x) { + if (f[x] != -1) { + return f[x]; + } + auto it = upper_bound(rewardValues.begin(), rewardValues.end(), x); + int ans = 0; + for (; it != rewardValues.end(); ++it) { + ans = max(ans, rewardValues[it - rewardValues.begin()] + dfs(x + *it)); + } + return f[x] = ans; + }; + return dfs(0); + } +}; ``` #### Go ```go +func maxTotalReward(rewardValues []int) int { + sort.Ints(rewardValues) + n := len(rewardValues) + f := make([]int, rewardValues[n-1]<<1) + for i := range f { + f[i] = -1 + } + var dfs func(int) int + dfs = func(x int) int { + if f[x] != -1 { + return f[x] + } + i := sort.SearchInts(rewardValues, x+1) + f[x] = 0 + for _, v := range rewardValues[i:] { + f[x] = max(f[x], v+dfs(x+v)) + } + return f[x] + } + return dfs(0) +} +``` +#### TypeScript + +```ts +function maxTotalReward(rewardValues: number[]): number { + rewardValues.sort((a, b) => a - b); + const search = (x: number): number => { + let [l, r] = [0, rewardValues.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (rewardValues[mid] > x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + const f: number[] = Array(rewardValues.at(-1)! << 1).fill(-1); + const dfs = (x: number): number => { + if (f[x] !== -1) { + return f[x]; + } + let ans = 0; + for (let i = search(x); i < rewardValues.length; ++i) { + ans = Math.max(ans, rewardValues[i] + dfs(x + rewardValues[i])); + } + return (f[x] = ans); + }; + return dfs(0); +} ``` diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.cpp b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.cpp new file mode 100644 index 0000000000000..360d5cf4a389c --- /dev/null +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.cpp @@ -0,0 +1,21 @@ +class Solution { +public: + int maxTotalReward(vector& rewardValues) { + sort(rewardValues.begin(), rewardValues.end()); + int n = rewardValues.size(); + int f[rewardValues.back() << 1]; + memset(f, -1, sizeof(f)); + function dfs = [&](int x) { + if (f[x] != -1) { + return f[x]; + } + auto it = upper_bound(rewardValues.begin(), rewardValues.end(), x); + int ans = 0; + for (; it != rewardValues.end(); ++it) { + ans = max(ans, rewardValues[it - rewardValues.begin()] + dfs(x + *it)); + } + return f[x] = ans; + }; + return dfs(0); + } +}; \ No newline at end of file diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.go b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.go new file mode 100644 index 0000000000000..b297e2cfcd452 --- /dev/null +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.go @@ -0,0 +1,21 @@ +func maxTotalReward(rewardValues []int) int { + sort.Ints(rewardValues) + n := len(rewardValues) + f := make([]int, rewardValues[n-1]<<1) + for i := range f { + f[i] = -1 + } + var dfs func(int) int + dfs = func(x int) int { + if f[x] != -1 { + return f[x] + } + i := sort.SearchInts(rewardValues, x+1) + f[x] = 0 + for _, v := range rewardValues[i:] { + f[x] = max(f[x], v+dfs(x+v)) + } + return f[x] + } + return dfs(0) +} \ No newline at end of file diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.java b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.java new file mode 100644 index 0000000000000..2d18a453fa523 --- /dev/null +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.java @@ -0,0 +1,25 @@ +class Solution { + private int[] nums; + private Integer[] f; + + public int maxTotalReward(int[] rewardValues) { + nums = rewardValues; + Arrays.sort(nums); + int n = nums.length; + f = new Integer[nums[n - 1] << 1]; + return dfs(0); + } + + private int dfs(int x) { + if (f[x] != null) { + return f[x]; + } + int i = Arrays.binarySearch(nums, x + 1); + i = i < 0 ? -i - 1 : i; + int ans = 0; + for (; i < nums.length; ++i) { + ans = Math.max(ans, nums[i] + dfs(x + nums[i])); + } + return f[x] = ans; + } +} \ No newline at end of file diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.py b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.py new file mode 100644 index 0000000000000..35e247b4a0b40 --- /dev/null +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.py @@ -0,0 +1,12 @@ +class Solution: + def maxTotalReward(self, rewardValues: List[int]) -> int: + @cache + def dfs(x: int) -> int: + i = bisect_right(rewardValues, x) + ans = 0 + for v in rewardValues[i:]: + ans = max(ans, v + dfs(x + v)) + return ans + + rewardValues.sort() + return dfs(0) diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.ts b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.ts new file mode 100644 index 0000000000000..9a852c18633ca --- /dev/null +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/Solution.ts @@ -0,0 +1,27 @@ +function maxTotalReward(rewardValues: number[]): number { + rewardValues.sort((a, b) => a - b); + const search = (x: number): number => { + let [l, r] = [0, rewardValues.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (rewardValues[mid] > x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + const f: number[] = Array(rewardValues.at(-1)! << 1).fill(-1); + const dfs = (x: number): number => { + if (f[x] !== -1) { + return f[x]; + } + let ans = 0; + for (let i = search(x); i < rewardValues.length; ++i) { + ans = Math.max(ans, rewardValues[i] + dfs(x + rewardValues[i])); + } + return (f[x] = ans); + }; + return dfs(0); +}