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.1959 #4155

Merged
merged 1 commit into from
Mar 13, 2025
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 @@ -74,6 +74,25 @@ tags:

### 方法一:动态规划

题目等价于我们将数组 $\textit{nums}$ 分成 $k + 1$ 段,那么每一段的浪费空间为该段的最大值乘以该段的长度减去该段的元素之和。我们累加每一段的浪费空间,即可得到总浪费空间。我们将 $k$ 加 $1$,那么就相当于将数组分成 $k$ 段。

因此,我们定义数组 $\textit{g}[i][j]$ 表示 $\textit{nums}[i..j]$ 的最大值乘以 $\textit{nums}[i..j]$ 的长度减去 $\textit{nums}[i..j]$ 的元素之和。我们在 $[0, n)$ 的范围内枚举 $i$,在 $[i, n)$ 的范围内枚举 $j$,用一个变量 $s$ 维护 $\textit{nums}[i..j]$ 的元素之和,用一个变量 $\textit{mx}$ 维护 $\textit{nums}[i..j]$ 的最大值,那么我们可以得到:

$$
\textit{g}[i][j] = \textit{mx} \times (j - i + 1) - s
$$

接下来,我们定义 $\textit{f}[i][j]$ 表示前 $i$ 个元素分成 $j$ 段的最小浪费空间。我们初始化 $\textit{f}[0][0] = 0$,其余位置初始化为无穷大。我们在 $[1, n]$ 的范围内枚举 $i$,在 $[1, k]$ 的范围内枚举 $j$,然后我们枚举前 $j - 1$ 段的最后一个元素 $h$,那么有:

$$
\textit{f}[i][j] = \min(\textit{f}[i][j], \
\textit{f}[h][j - 1] + \textit{g}[h][i - 1])
$$

最终答案为 $\textit{f}[n][k]$。

时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times (n + k))$。其中 $n$ 为数组 $\textit{nums}$ 的长度。

<!-- tabs:start -->

#### Python3
Expand Down Expand Up @@ -203,6 +222,75 @@ func minSpaceWastedKResizing(nums []int, k int) int {
}
```

#### TypeScript

```ts
function minSpaceWastedKResizing(nums: number[], k: number): number {
k += 1;
const n = nums.length;
const g: number[][] = Array.from({ length: n }, () => Array(n).fill(0));

for (let i = 0; i < n; i++) {
let s = 0,
mx = 0;
for (let j = i; j < n; j++) {
s += nums[j];
mx = Math.max(mx, nums[j]);
g[i][j] = mx * (j - i + 1) - s;
}
}

const inf = Number.POSITIVE_INFINITY;
const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(inf));
f[0][0] = 0;

for (let i = 1; i <= n; i++) {
for (let j = 1; j <= k; j++) {
for (let h = 0; h < i; h++) {
f[i][j] = Math.min(f[i][j], f[h][j - 1] + g[h][i - 1]);
}
}
}

return f[n][k];
}
```

#### Rust

```rust
impl Solution {
pub fn min_space_wasted_k_resizing(nums: Vec<i32>, k: i32) -> i32 {
let mut k = k + 1;
let n = nums.len();
let mut g = vec![vec![0; n]; n];

for i in 0..n {
let (mut s, mut mx) = (0, 0);
for j in i..n {
s += nums[j];
mx = mx.max(nums[j]);
g[i][j] = mx * (j as i32 - i as i32 + 1) - s;
}
}

let inf = 0x3f3f3f3f;
let mut f = vec![vec![inf; (k + 1) as usize]; n + 1];
f[0][0] = 0;

for i in 1..=n {
for j in 1..=k as usize {
for h in 0..i {
f[i][j] = f[i][j].min(f[h][j - 1] + g[h][i - 1]);
}
}
}

f[n][k as usize]
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The total wasted space is (20 - 10) + (20 - 20) = 10.
<strong>Input:</strong> nums = [10,20,30], k = 1
<strong>Output:</strong> 10
<strong>Explanation:</strong> size = [20,20,30].
We can set the initial size to be 20 and resize to 30 at time 2.
We can set the initial size to be 20 and resize to 30 at time 2.
The total wasted space is (20 - 10) + (20 - 20) + (30 - 30) = 10.
</pre>

Expand Down Expand Up @@ -73,7 +73,20 @@ The total wasted space is (10 - 10) + (20 - 20) + (20 - 15) + (30 - 30) + (30 -

<!-- solution:start -->

### Solution 1
Solution 1: Dynamic Programming
The problem is equivalent to dividing the array $\textit{nums}$ into $k + 1$ segments. The wasted space for each segment is the maximum value of that segment multiplied by the length of the segment minus the sum of the elements in that segment. By summing the wasted space of each segment, we get the total wasted space. By adding 1 to $k$, we are effectively dividing the array into $k$ segments.

Therefore, we define an array $\textit{g}[i][j]$ to represent the wasted space for the segment $\textit{nums}[i..j]$, which is the maximum value of $\textit{nums}[i..j]$ multiplied by the length of $\textit{nums}[i..j]$ minus the sum of the elements in $\textit{nums}[i..j]$. We iterate over $i$ in the range $[0, n)$ and $j$ in the range $[i, n)$, using a variable $s$ to maintain the sum of the elements in $\textit{nums}[i..j]$ and a variable $\textit{mx}$ to maintain the maximum value of $\textit{nums}[i..j]$. Then we can get:

$$ \textit{g}[i][j] = \textit{mx} \times (j - i + 1) - s $$

Next, we define $\textit{f}[i][j]$ to represent the minimum wasted space for dividing the first $i$ elements into $j$ segments. We initialize $\textit{f}[0][0] = 0$ and the other positions to infinity. We iterate over $i$ in the range $[1, n]$ and $j$ in the range $[1, k]$, then we iterate over the last element $h$ of the previous $j - 1$ segments. Then we have:

$$ \textit{f}[i][j] = \min(\textit{f}[i][j], \textit{f}[h][j - 1] + \textit{g}[h][i - 1]) $$

The final answer is $\textit{f}[n][k]$.

The time complexity is $O(n^2 \times k)$, and the space complexity is $O(n \times (n + k))$. Where $n$ is the length of the array $\textit{nums}$.

<!-- tabs:start -->

Expand Down Expand Up @@ -204,6 +217,75 @@ func minSpaceWastedKResizing(nums []int, k int) int {
}
```

#### TypeScript

```ts
function minSpaceWastedKResizing(nums: number[], k: number): number {
k += 1;
const n = nums.length;
const g: number[][] = Array.from({ length: n }, () => Array(n).fill(0));

for (let i = 0; i < n; i++) {
let s = 0,
mx = 0;
for (let j = i; j < n; j++) {
s += nums[j];
mx = Math.max(mx, nums[j]);
g[i][j] = mx * (j - i + 1) - s;
}
}

const inf = Number.POSITIVE_INFINITY;
const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(inf));
f[0][0] = 0;

for (let i = 1; i <= n; i++) {
for (let j = 1; j <= k; j++) {
for (let h = 0; h < i; h++) {
f[i][j] = Math.min(f[i][j], f[h][j - 1] + g[h][i - 1]);
}
}
}

return f[n][k];
}
```

#### Rust

```rust
impl Solution {
pub fn min_space_wasted_k_resizing(nums: Vec<i32>, k: i32) -> i32 {
let mut k = k + 1;
let n = nums.len();
let mut g = vec![vec![0; n]; n];

for i in 0..n {
let (mut s, mut mx) = (0, 0);
for j in i..n {
s += nums[j];
mx = mx.max(nums[j]);
g[i][j] = mx * (j as i32 - i as i32 + 1) - s;
}
}

let inf = 0x3f3f3f3f;
let mut f = vec![vec![inf; (k + 1) as usize]; n + 1];
f[0][0] = 0;

for i in 1..=n {
for j in 1..=k as usize {
for h in 0..i {
f[i][j] = f[i][j].min(f[h][j - 1] + g[h][i - 1]);
}
}
}

f[n][k as usize]
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
impl Solution {
pub fn min_space_wasted_k_resizing(nums: Vec<i32>, k: i32) -> i32 {
let mut k = k + 1;
let n = nums.len();
let mut g = vec![vec![0; n]; n];

for i in 0..n {
let (mut s, mut mx) = (0, 0);
for j in i..n {
s += nums[j];
mx = mx.max(nums[j]);
g[i][j] = mx * (j as i32 - i as i32 + 1) - s;
}
}

let inf = 0x3f3f3f3f;
let mut f = vec![vec![inf; (k + 1) as usize]; n + 1];
f[0][0] = 0;

for i in 1..=n {
for j in 1..=k as usize {
for h in 0..i {
f[i][j] = f[i][j].min(f[h][j - 1] + g[h][i - 1]);
}
}
}

f[n][k as usize]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
function minSpaceWastedKResizing(nums: number[], k: number): number {
k += 1;
const n = nums.length;
const g: number[][] = Array.from({ length: n }, () => Array(n).fill(0));

for (let i = 0; i < n; i++) {
let s = 0,
mx = 0;
for (let j = i; j < n; j++) {
s += nums[j];
mx = Math.max(mx, nums[j]);
g[i][j] = mx * (j - i + 1) - s;
}
}

const inf = Number.POSITIVE_INFINITY;
const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(inf));
f[0][0] = 0;

for (let i = 1; i <= n; i++) {
for (let j = 1; j <= k; j++) {
for (let h = 0; h < i; h++) {
f[i][j] = Math.min(f[i][j], f[h][j - 1] + g[h][i - 1]);
}
}
}

return f[n][k];
}