From 2ad9f8a3da874b32d0f92071501661745e1997b7 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 24 Mar 2025 21:04:09 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.0960 No.0960.Delete Columns to Make Sorted III --- .../README.md | 136 ++++++++++------- .../README_EN.md | 137 +++++++++++------- .../Solution.cpp | 19 +-- .../Solution.go | 30 ++-- .../Solution.java | 30 ++-- .../Solution.py | 8 +- .../Solution.rs | 16 ++ .../Solution.ts | 19 +++ .../README.md | 4 +- .../README_EN.md | 12 +- 10 files changed, 259 insertions(+), 152 deletions(-) create mode 100644 solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.rs create mode 100644 solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.ts diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/README.md b/solution/0900-0999/0960.Delete Columns to Make Sorted III/README.md index f56f44175d435..6a290941c46bc 100644 --- a/solution/0900-0999/0960.Delete Columns to Make Sorted III/README.md +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/README.md @@ -75,7 +75,15 @@ tags: -### 方法一 +### 方法一:动态规划 + +我们定义 $f[i]$ 表示以第 $i$ 列结尾的最长不下降子序列的长度,初始时 $f[i] = 1$,答案即为 $n - \max(f)$。 + +考虑计算 $f[i]$,我们可以枚举 $j < i$,如果对于所有的字符串 $s$,有 $s[j] \le s[i]$,那么 $f[i] = \max(f[i], f[j] + 1)$。 + +最后,我们返回 $n - \max(f)$。 + +时间复杂度 $O(n^2 \times m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 $\textit{strs}$ 每个字符串的长度和数组的长度。 @@ -85,12 +93,12 @@ tags: class Solution: def minDeletionSize(self, strs: List[str]) -> int: n = len(strs[0]) - dp = [1] * n - for i in range(1, n): + f = [1] * n + for i in range(n): for j in range(i): if all(s[j] <= s[i] for s in strs): - dp[i] = max(dp[i], dp[j] + 1) - return n - max(dp) + f[i] = max(f[i], f[j] + 1) + return n - max(f) ``` #### Java @@ -99,27 +107,23 @@ class Solution: class Solution { public int minDeletionSize(String[] strs) { int n = strs[0].length(); - int[] dp = new int[n]; - Arrays.fill(dp, 1); - int mx = 1; + int[] f = new int[n]; + Arrays.fill(f, 1); for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { - if (check(i, j, strs)) { - dp[i] = Math.max(dp[i], dp[j] + 1); + boolean ok = true; + for (String s : strs) { + if (s.charAt(j) > s.charAt(i)) { + ok = false; + break; + } + } + if (ok) { + f[i] = Math.max(f[i], f[j] + 1); } - } - mx = Math.max(mx, dp[i]); - } - return n - mx; - } - - private boolean check(int i, int j, String[] strs) { - for (String s : strs) { - if (s.charAt(i) < s.charAt(j)) { - return false; } } - return true; + return n - Arrays.stream(f).max().getAsInt(); } } ``` @@ -131,24 +135,15 @@ class Solution { public: int minDeletionSize(vector& strs) { int n = strs[0].size(); - vector dp(n, 1); - int mx = 1; + vector f(n, 1); for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { - if (check(i, j, strs)) { - dp[i] = max(dp[i], dp[j] + 1); + if (ranges::all_of(strs, [&](const string& s) { return s[j] <= s[i]; })) { + f[i] = max(f[i], f[j] + 1); } } - mx = max(mx, dp[i]); } - return n - mx; - } - - bool check(int i, int j, vector& strs) { - for (string& s : strs) - if (s[i] < s[j]) - return false; - return true; + return n - ranges::max(f); } }; ``` @@ -158,27 +153,70 @@ public: ```go func minDeletionSize(strs []string) int { n := len(strs[0]) - dp := make([]int, n) - mx := 1 - dp[0] = 1 - check := func(i, j int) bool { - for _, s := range strs { - if s[i] < s[j] { - return false - } - } - return true + f := make([]int, n) + for i := range f { + f[i] = 1 } for i := 1; i < n; i++ { - dp[i] = 1 for j := 0; j < i; j++ { - if check(i, j) { - dp[i] = max(dp[i], dp[j]+1) + ok := true + for _, s := range strs { + if s[j] > s[i] { + ok = false + break + } + } + if ok { + f[i] = max(f[i], f[j]+1) } } - mx = max(mx, dp[i]) } - return n - mx + return n - slices.Max(f) +} +``` + +#### TypeScript + +```ts +function minDeletionSize(strs: string[]): number { + const n = strs[0].length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; i++) { + for (let j = 0; j < i; j++) { + let ok = true; + for (const s of strs) { + if (s[j] > s[i]) { + ok = false; + break; + } + } + if (ok) { + f[i] = Math.max(f[i], f[j] + 1); + } + } + } + return n - Math.max(...f); +} +``` + +#### Rust + +```rust +impl Solution { + pub fn min_deletion_size(strs: Vec) -> i32 { + let n = strs[0].len(); + let mut f = vec![1; n]; + + for i in 1..n { + for j in 0..i { + if strs.iter().all(|s| s.as_bytes()[j] <= s.as_bytes()[i]) { + f[i] = f[i].max(f[j] + 1); + } + } + } + + (n - *f.iter().max().unwrap()) as i32 + } } ``` diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/README_EN.md b/solution/0900-0999/0960.Delete Columns to Make Sorted III/README_EN.md index a0e4da1b1996d..32d7bef83610f 100644 --- a/solution/0900-0999/0960.Delete Columns to Make Sorted III/README_EN.md +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/README_EN.md @@ -72,7 +72,16 @@ Note that strs[0] > strs[1] - the array strs is not necessarily in lexicograp -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i]$ as the length of the longest non-decreasing subsequence ending at column $i$. Initially, $f[i] = 1$, and the final answer is $n - \max(f)$. + +To compute $f[i]$, we iterate over all $j < i$. If for all strings $s$, we have $s[j] \leq s[i]$, then we update $f[i]$ as follows: +$$ f[i] = \max(f[i], f[j] + 1) $$ + +Finally, we return $n - \max(f)$. + +The time complexity is $O(n^2 \times m)$, and the space complexity is $O(n)$, where $n$ is the length of each string in the array $\textit{strs}$, and $m$ is the number of strings in the array. @@ -82,12 +91,12 @@ Note that strs[0] > strs[1] - the array strs is not necessarily in lexicograp class Solution: def minDeletionSize(self, strs: List[str]) -> int: n = len(strs[0]) - dp = [1] * n - for i in range(1, n): + f = [1] * n + for i in range(n): for j in range(i): if all(s[j] <= s[i] for s in strs): - dp[i] = max(dp[i], dp[j] + 1) - return n - max(dp) + f[i] = max(f[i], f[j] + 1) + return n - max(f) ``` #### Java @@ -96,27 +105,23 @@ class Solution: class Solution { public int minDeletionSize(String[] strs) { int n = strs[0].length(); - int[] dp = new int[n]; - Arrays.fill(dp, 1); - int mx = 1; + int[] f = new int[n]; + Arrays.fill(f, 1); for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { - if (check(i, j, strs)) { - dp[i] = Math.max(dp[i], dp[j] + 1); + boolean ok = true; + for (String s : strs) { + if (s.charAt(j) > s.charAt(i)) { + ok = false; + break; + } + } + if (ok) { + f[i] = Math.max(f[i], f[j] + 1); } - } - mx = Math.max(mx, dp[i]); - } - return n - mx; - } - - private boolean check(int i, int j, String[] strs) { - for (String s : strs) { - if (s.charAt(i) < s.charAt(j)) { - return false; } } - return true; + return n - Arrays.stream(f).max().getAsInt(); } } ``` @@ -128,24 +133,15 @@ class Solution { public: int minDeletionSize(vector& strs) { int n = strs[0].size(); - vector dp(n, 1); - int mx = 1; + vector f(n, 1); for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { - if (check(i, j, strs)) { - dp[i] = max(dp[i], dp[j] + 1); + if (ranges::all_of(strs, [&](const string& s) { return s[j] <= s[i]; })) { + f[i] = max(f[i], f[j] + 1); } } - mx = max(mx, dp[i]); } - return n - mx; - } - - bool check(int i, int j, vector& strs) { - for (string& s : strs) - if (s[i] < s[j]) - return false; - return true; + return n - ranges::max(f); } }; ``` @@ -155,27 +151,70 @@ public: ```go func minDeletionSize(strs []string) int { n := len(strs[0]) - dp := make([]int, n) - mx := 1 - dp[0] = 1 - check := func(i, j int) bool { - for _, s := range strs { - if s[i] < s[j] { - return false - } - } - return true + f := make([]int, n) + for i := range f { + f[i] = 1 } for i := 1; i < n; i++ { - dp[i] = 1 for j := 0; j < i; j++ { - if check(i, j) { - dp[i] = max(dp[i], dp[j]+1) + ok := true + for _, s := range strs { + if s[j] > s[i] { + ok = false + break + } + } + if ok { + f[i] = max(f[i], f[j]+1) } } - mx = max(mx, dp[i]) } - return n - mx + return n - slices.Max(f) +} +``` + +#### TypeScript + +```ts +function minDeletionSize(strs: string[]): number { + const n = strs[0].length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; i++) { + for (let j = 0; j < i; j++) { + let ok = true; + for (const s of strs) { + if (s[j] > s[i]) { + ok = false; + break; + } + } + if (ok) { + f[i] = Math.max(f[i], f[j] + 1); + } + } + } + return n - Math.max(...f); +} +``` + +#### Rust + +```rust +impl Solution { + pub fn min_deletion_size(strs: Vec) -> i32 { + let n = strs[0].len(); + let mut f = vec![1; n]; + + for i in 1..n { + for j in 0..i { + if strs.iter().all(|s| s.as_bytes()[j] <= s.as_bytes()[i]) { + f[i] = f[i].max(f[j] + 1); + } + } + } + + (n - *f.iter().max().unwrap()) as i32 + } } ``` diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.cpp b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.cpp index ec0ec1f91a386..ed77da29fd651 100644 --- a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.cpp +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.cpp @@ -2,23 +2,14 @@ class Solution { public: int minDeletionSize(vector& strs) { int n = strs[0].size(); - vector dp(n, 1); - int mx = 1; + vector f(n, 1); for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { - if (check(i, j, strs)) { - dp[i] = max(dp[i], dp[j] + 1); + if (ranges::all_of(strs, [&](const string& s) { return s[j] <= s[i]; })) { + f[i] = max(f[i], f[j] + 1); } } - mx = max(mx, dp[i]); } - return n - mx; + return n - ranges::max(f); } - - bool check(int i, int j, vector& strs) { - for (string& s : strs) - if (s[i] < s[j]) - return false; - return true; - } -}; \ No newline at end of file +}; diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.go b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.go index 88f9b62f5c2f7..6320843c1d48d 100644 --- a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.go +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.go @@ -1,24 +1,22 @@ func minDeletionSize(strs []string) int { n := len(strs[0]) - dp := make([]int, n) - mx := 1 - dp[0] = 1 - check := func(i, j int) bool { - for _, s := range strs { - if s[i] < s[j] { - return false - } - } - return true + f := make([]int, n) + for i := range f { + f[i] = 1 } for i := 1; i < n; i++ { - dp[i] = 1 for j := 0; j < i; j++ { - if check(i, j) { - dp[i] = max(dp[i], dp[j]+1) + ok := true + for _, s := range strs { + if s[j] > s[i] { + ok = false + break + } + } + if ok { + f[i] = max(f[i], f[j]+1) } } - mx = max(mx, dp[i]) } - return n - mx -} \ No newline at end of file + return n - slices.Max(f) +} diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.java b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.java index 2de0dfcc649eb..a231228517026 100644 --- a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.java +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.java @@ -1,26 +1,22 @@ class Solution { public int minDeletionSize(String[] strs) { int n = strs[0].length(); - int[] dp = new int[n]; - Arrays.fill(dp, 1); - int mx = 1; + int[] f = new int[n]; + Arrays.fill(f, 1); for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { - if (check(i, j, strs)) { - dp[i] = Math.max(dp[i], dp[j] + 1); + boolean ok = true; + for (String s : strs) { + if (s.charAt(j) > s.charAt(i)) { + ok = false; + break; + } + } + if (ok) { + f[i] = Math.max(f[i], f[j] + 1); } - } - mx = Math.max(mx, dp[i]); - } - return n - mx; - } - - private boolean check(int i, int j, String[] strs) { - for (String s : strs) { - if (s.charAt(i) < s.charAt(j)) { - return false; } } - return true; + return n - Arrays.stream(f).max().getAsInt(); } -} \ No newline at end of file +} diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.py b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.py index c9bc149baa62e..23e7b6b973048 100644 --- a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.py +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.py @@ -1,9 +1,9 @@ class Solution: def minDeletionSize(self, strs: List[str]) -> int: n = len(strs[0]) - dp = [1] * n - for i in range(1, n): + f = [1] * n + for i in range(n): for j in range(i): if all(s[j] <= s[i] for s in strs): - dp[i] = max(dp[i], dp[j] + 1) - return n - max(dp) + f[i] = max(f[i], f[j] + 1) + return n - max(f) diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.rs b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.rs new file mode 100644 index 0000000000000..3ad0e1adb0b2d --- /dev/null +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.rs @@ -0,0 +1,16 @@ +impl Solution { + pub fn min_deletion_size(strs: Vec) -> i32 { + let n = strs[0].len(); + let mut f = vec![1; n]; + + for i in 1..n { + for j in 0..i { + if strs.iter().all(|s| s.as_bytes()[j] <= s.as_bytes()[i]) { + f[i] = f[i].max(f[j] + 1); + } + } + } + + (n - *f.iter().max().unwrap()) as i32 + } +} diff --git a/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.ts b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.ts new file mode 100644 index 0000000000000..5471c6a12ef0e --- /dev/null +++ b/solution/0900-0999/0960.Delete Columns to Make Sorted III/Solution.ts @@ -0,0 +1,19 @@ +function minDeletionSize(strs: string[]): number { + const n = strs[0].length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; i++) { + for (let j = 0; j < i; j++) { + let ok = true; + for (const s of strs) { + if (s[j] > s[i]) { + ok = false; + break; + } + } + if (ok) { + f[i] = Math.max(f[i], f[j] + 1); + } + } + } + return n - Math.max(...f); +} diff --git a/solution/2600-2699/2600.K Items With the Maximum Sum/README.md b/solution/2600-2699/2600.K Items With the Maximum Sum/README.md index aa3ebe42346d8..b875702154eb5 100644 --- a/solution/2600-2699/2600.K Items With the Maximum Sum/README.md +++ b/solution/2600-2699/2600.K Items With the Maximum Sum/README.md @@ -74,8 +74,8 @@ tags: 因此: - 如果袋子中的物品标记为 $1$ 的数量大于等于 $k$,那么取 $k$ 件物品,数字之和为 $k$; -- 如果袋子中的物品标记为 $1$ 的数量小于 $k$,那么取 $numOnes$ 件物品,数字之和为 $numOnes$;如果标记为 $0$ 的物品数量大于等于 $k - numOnes$,那么再取 $k - numOnes$ 件物品,数字之和还是 $numOnes$; -- 否则,我们再从标记为 $-1$ 的物品中取 $k - numOnes - numZeros$ 件物品,数字之和为 $numOnes - (k - numOnes - numZeros)$。 +- 如果袋子中的物品标记为 $1$ 的数量小于 $k$,那么取 $\textit{numOnes}$ 件物品,数字之和为 $\textit{numOnes}$;如果标记为 $0$ 的物品数量大于等于 $k - \textit{numOnes}$,那么再取 $k - \textit{numOnes}$ 件物品,数字之和还是 $\textit{numOnes}$; +- 否则,我们再从标记为 $-1$ 的物品中取 $k - \textit{numOnes} - \textit{numZeros}$ 件物品,数字之和为 $\textit{numOnes} - (k - \textit{numOnes} - \textit{numZeros})$。 时间复杂度 $O(1)$,空间复杂度 $O(1)$。 diff --git a/solution/2600-2699/2600.K Items With the Maximum Sum/README_EN.md b/solution/2600-2699/2600.K Items With the Maximum Sum/README_EN.md index 7a1a97bd5c100..6bbce952b058b 100644 --- a/solution/2600-2699/2600.K Items With the Maximum Sum/README_EN.md +++ b/solution/2600-2699/2600.K Items With the Maximum Sum/README_EN.md @@ -66,7 +66,17 @@ It can be proven that 3 is the maximum possible sum. -### Solution 1 +### Solution 1: Greedy + +According to the problem description, we should take as many items marked as $1$ as possible, then take items marked as $0$, and finally take items marked as $-1$. + +Thus: + +- If the number of items marked as $1$ in the bag is greater than or equal to $k$, we take $k$ items, and the sum of the numbers is $k$. +- If the number of items marked as $1$ is less than $k$, we take $\textit{numOnes}$ items, resulting in a sum of $\textit{numOnes}$. If the number of items marked as $0$ is greater than or equal to $k - \textit{numOnes}$, we take $k - \textit{numOnes}$ more items, keeping the sum at $\textit{numOnes}$. +- Otherwise, we take $k - \textit{numOnes} - \textit{numZeros}$ items from those marked as $-1$, resulting in a sum of $\textit{numOnes} - (k - \textit{numOnes} - \textit{numZeros})$. + +The time complexity is $O(1)$, and the space complexity is $O(1)$.