Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lc problem: No.3098 #3311

Merged
merged 3 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,18 @@ public:
int n = num.size();
int f[n][25];
memset(f, -1, sizeof(f));
function<int(int, int)> dfs = [&](int i, int k) -> int {
auto dfs = [&](auto&& dfs, int i, int k) -> int {
if (i == n) {
return k == 0 ? 0 : n;
}
if (f[i][k] != -1) {
return f[i][k];
}
f[i][k] = dfs(i + 1, k) + 1;
f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25));
f[i][k] = dfs(dfs, i + 1, k) + 1;
f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25));
return f[i][k];
};
return dfs(0, 0);
return dfs(dfs, 0, 0);
}
};
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,18 @@ public:
int n = num.size();
int f[n][25];
memset(f, -1, sizeof(f));
function<int(int, int)> dfs = [&](int i, int k) -> int {
auto dfs = [&](auto&& dfs, int i, int k) -> int {
if (i == n) {
return k == 0 ? 0 : n;
}
if (f[i][k] != -1) {
return f[i][k];
}
f[i][k] = dfs(i + 1, k) + 1;
f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25));
f[i][k] = dfs(dfs, i + 1, k) + 1;
f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25));
return f[i][k];
};
return dfs(0, 0);
return dfs(dfs, 0, 0);
}
};
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ class Solution {
int n = num.size();
int f[n][25];
memset(f, -1, sizeof(f));
function<int(int, int)> dfs = [&](int i, int k) -> int {
auto dfs = [&](auto&& dfs, int i, int k) -> int {
if (i == n) {
return k == 0 ? 0 : n;
}
if (f[i][k] != -1) {
return f[i][k];
}
f[i][k] = dfs(i + 1, k) + 1;
f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25));
f[i][k] = dfs(dfs, i + 1, k) + 1;
f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25));
return f[i][k];
};
return dfs(0, 0);
return dfs(dfs, 0, 0);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,14 @@ tags:

### 方法一:记忆化搜索

我们设计一个函数 $dfs(i, j, k, mi)$,表示当前处理到第 $i$ 个元素,上一个选取的是第 $j$ 个元素,还需要选取 $k$ 个元素,当前的最小差值为 $mi$ 时,能量和的值。那么答案就是 $dfs(0, n, k, +\infty)$。
由于题目涉及子序列元素的最小差值,我们不妨对数组 $\textit{nums}$ 进行排序,这样可以方便我们计算子序列元素的最小差值。

接下来,我们设计一个函数 $dfs(i, j, k, mi)$,表示当前处理到第 $i$ 个元素,上一个选取的是第 $j$ 个元素,还需要选取 $k$ 个元素,当前的最小差值为 $mi$ 时,能量和的值。那么答案就是 $dfs(0, n, k, +\infty)$。(若上一个选取的是第 $n$ 个元素,表示之前没有选取过元素)

函数 $dfs(i, j, k, mi)$ 的执行过程如下:

- 如果 $i \geq n$,表示已经处理完了所有的元素,如果 $k = 0$,返回 $mi$,否则返回 $0$;
- 如果剩余的元素个数 $n - i$ 不足 $k$ 个,返回 $0$;
- 否则,我们可以选择不选取第 $i$ 个元素,可以获得的能量和为 $dfs(i + 1, j, k, mi)$;
- 也可以选择选取第 $i$ 个元素。如果 $j = n$,表示之前没有选取过元素,那么可以获得的能量和为 $dfs(i + 1, i, k - 1, mi)$;否则,可以获得的能量和为 $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$。
- 我们累加上述结果,并对 $10^9 + 7$ 取模后返回。
Expand All @@ -108,6 +111,8 @@ class Solution:
def dfs(i: int, j: int, k: int, mi: int) -> int:
if i >= n:
return mi if k == 0 else 0
if n - i < k:
return 0
ans = dfs(i + 1, j, k, mi)
if j == n:
ans += dfs(i + 1, i, k - 1, mi)
Expand Down Expand Up @@ -140,6 +145,9 @@ class Solution {
if (i >= nums.length) {
return k == 0 ? mi : 0;
}
if (nums.length - i < k) {
return 0;
}
long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k;
if (f.containsKey(key)) {
return f.get(key);
Expand All @@ -157,6 +165,42 @@ class Solution {
}
```

#### C++

```cpp
class Solution {
public:
int sumOfPowers(vector<int>& nums, int k) {
unordered_map<long long, int> f;
const int mod = 1e9 + 7;
int n = nums.size();
sort(nums.begin(), nums.end());
auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int {
if (i >= n) {
return k == 0 ? mi : 0;
}
if (n - i < k) {
return 0;
}
long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k;
if (f.contains(key)) {
return f[key];
}
long long ans = dfs(dfs, i + 1, j, k, mi);
if (j == n) {
ans += dfs(dfs, i + 1, i, k - 1, mi);
} else {
ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j]));
}
ans %= mod;
f[key] = ans;
return f[key];
};
return dfs(dfs, 0, n, k, INT_MAX);
}
};
```

#### Go

```go
Expand All @@ -173,6 +217,9 @@ func sumOfPowers(nums []int, k int) int {
}
return 0
}
if n-i < k {
return 0
}
key := mi<<18 | (i << 12) | (j << 6) | k
if v, ok := f[key]; ok {
return v
Expand All @@ -191,6 +238,47 @@ func sumOfPowers(nums []int, k int) int {
}
```

#### TypeScript

```ts
function sumOfPowers(nums: number[], k: number): number {
const mod = BigInt(1e9 + 7);
nums.sort((a, b) => a - b);
const n = nums.length;
const f: Map<bigint, bigint> = new Map();
function dfs(i: number, j: number, k: number, mi: number): bigint {
if (i >= n) {
if (k === 0) {
return BigInt(mi);
}
return BigInt(0);
}
if (n - i < k) {
return BigInt(0);
}
const key =
(BigInt(mi) << BigInt(18)) |
(BigInt(i) << BigInt(12)) |
(BigInt(j) << BigInt(6)) |
BigInt(k);
if (f.has(key)) {
return f.get(key)!;
}
let ans = dfs(i + 1, j, k, mi);
if (j === n) {
ans += dfs(i + 1, i, k - 1, mi);
} else {
ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j]));
}
ans %= mod;
f.set(key, ans);
return ans;
}

return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER));
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,21 @@ tags:

### Solution 1: Memoization Search

We design a function $dfs(i, j, k, mi)$, which represents the energy sum value when we are currently processing the $i$-th element, the last selected element is the $j$-th element, we still need to select $k$ elements, and the current minimum difference is $mi$. The answer is $dfs(0, n, k, +\infty)$.
Given the problem involves the minimum difference between elements of a subsequence, we might as well sort the array $\textit{nums}$, which facilitates the calculation of the minimum difference between subsequence elements.

Next, we design a function $dfs(i, j, k, mi)$, representing the value of the energy sum when processing the $i$-th element, the last selected element is the $j$-th element, $k$ more elements need to be selected, and the current minimum difference is $mi$. Therefore, the answer is $dfs(0, n, k, +\infty)$ (If the last selected element is the $n$-th element, it indicates that no element has been selected before).

The execution process of the function $dfs(i, j, k, mi)$ is as follows:

- If $i \geq n$, it means that all elements have been processed. If $k = 0$, return $mi$, otherwise return $0$;
- Otherwise, we can choose not to select the $i$-th element, and the energy sum obtained is $dfs(i + 1, j, k, mi)$;
- We can also choose to select the $i$-th element. If $j = n$, it means that no element has been selected before, and the energy sum obtained is $dfs(i + 1, i, k - 1, mi)$; otherwise, the energy sum obtained is $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$.
- We add up the above results, take the modulus of $10^9 + 7$, and return.
- If $i \geq n$, it means all elements have been processed. If $k = 0$, return $mi$; otherwise, return $0$.
- If the remaining number of elements $n - i$ is less than $k$, return $0$.
- Otherwise, we can choose not to select the $i$-th element, and the energy sum obtained is $dfs(i + 1, j, k, mi)$.
- We can also choose to select the $i$-th element. If $j = n$, it means no element has been selected before, then the energy sum obtained is $dfs(i + 1, i, k - 1, mi)$; otherwise, the energy sum obtained is $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$.
- We add up the above results and return the result modulo $10^9 + 7$.

To avoid repeated calculations, we can use the method of memoization search to save the calculated results.
To avoid repeated calculations, we can use memoization, saving the results that have already been calculated.

The time complexity is $O(n^4 \times k)$, and the space complexity is $O(n^4 \times k)$. Where $n$ is the length of the array.
The time complexity is $O(n^4 \times k)$, and the space complexity is $O(n^4 \times k)$. Here, $n$ is the length of the array.

<!-- tabs:start -->

Expand All @@ -106,6 +109,8 @@ class Solution:
def dfs(i: int, j: int, k: int, mi: int) -> int:
if i >= n:
return mi if k == 0 else 0
if n - i < k:
return 0
ans = dfs(i + 1, j, k, mi)
if j == n:
ans += dfs(i + 1, i, k - 1, mi)
Expand Down Expand Up @@ -138,6 +143,9 @@ class Solution {
if (i >= nums.length) {
return k == 0 ? mi : 0;
}
if (nums.length - i < k) {
return 0;
}
long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k;
if (f.containsKey(key)) {
return f.get(key);
Expand All @@ -155,6 +163,42 @@ class Solution {
}
```

#### C++

```cpp
class Solution {
public:
int sumOfPowers(vector<int>& nums, int k) {
unordered_map<long long, int> f;
const int mod = 1e9 + 7;
int n = nums.size();
sort(nums.begin(), nums.end());
auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int {
if (i >= n) {
return k == 0 ? mi : 0;
}
if (n - i < k) {
return 0;
}
long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k;
if (f.contains(key)) {
return f[key];
}
long long ans = dfs(dfs, i + 1, j, k, mi);
if (j == n) {
ans += dfs(dfs, i + 1, i, k - 1, mi);
} else {
ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j]));
}
ans %= mod;
f[key] = ans;
return f[key];
};
return dfs(dfs, 0, n, k, INT_MAX);
}
};
```

#### Go

```go
Expand All @@ -171,6 +215,9 @@ func sumOfPowers(nums []int, k int) int {
}
return 0
}
if n-i < k {
return 0
}
key := mi<<18 | (i << 12) | (j << 6) | k
if v, ok := f[key]; ok {
return v
Expand All @@ -189,6 +236,47 @@ func sumOfPowers(nums []int, k int) int {
}
```

#### TypeScript

```ts
function sumOfPowers(nums: number[], k: number): number {
const mod = BigInt(1e9 + 7);
nums.sort((a, b) => a - b);
const n = nums.length;
const f: Map<bigint, bigint> = new Map();
function dfs(i: number, j: number, k: number, mi: number): bigint {
if (i >= n) {
if (k === 0) {
return BigInt(mi);
}
return BigInt(0);
}
if (n - i < k) {
return BigInt(0);
}
const key =
(BigInt(mi) << BigInt(18)) |
(BigInt(i) << BigInt(12)) |
(BigInt(j) << BigInt(6)) |
BigInt(k);
if (f.has(key)) {
return f.get(key)!;
}
let ans = dfs(i + 1, j, k, mi);
if (j === n) {
ans += dfs(i + 1, i, k - 1, mi);
} else {
ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j]));
}
ans %= mod;
f.set(key, ans);
return ans;
}

return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER));
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class Solution {
public:
int sumOfPowers(vector<int>& nums, int k) {
unordered_map<long long, int> f;
const int mod = 1e9 + 7;
int n = nums.size();
sort(nums.begin(), nums.end());
auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int {
if (i >= n) {
return k == 0 ? mi : 0;
}
if (n - i < k) {
return 0;
}
long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k;
if (f.contains(key)) {
return f[key];
}
long long ans = dfs(dfs, i + 1, j, k, mi);
if (j == n) {
ans += dfs(dfs, i + 1, i, k - 1, mi);
} else {
ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j]));
}
ans %= mod;
f[key] = ans;
return f[key];
};
return dfs(dfs, 0, n, k, INT_MAX);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ func sumOfPowers(nums []int, k int) int {
}
return 0
}
if n-i < k {
return 0
}
key := mi<<18 | (i << 12) | (j << 6) | k
if v, ok := f[key]; ok {
return v
Expand Down
Loading
Loading