diff --git a/solution/0500-0599/0516.Longest Palindromic Subsequence/README.md b/solution/0500-0599/0516.Longest Palindromic Subsequence/README.md index 2f928f2a0e156..94ac13da55274 100644 --- a/solution/0500-0599/0516.Longest Palindromic Subsequence/README.md +++ b/solution/0500-0599/0516.Longest Palindromic Subsequence/README.md @@ -41,7 +41,17 @@ ## 解法 -### 方法一 +### 方法一:动态规划 + +我们定义 $f[i][j]$ 表示字符串 $s$ 的第 $i$ 个字符到第 $j$ 个字符之间的最长回文子序列的长度。初始时 $f[i][i] = 1$,其余位置的值均为 $0$。 + +如果 $s[i] = s[j]$,那么 $f[i][j] = f[i + 1][j - 1] + 2$;否则 $f[i][j] = \max(f[i + 1][j], f[i][j - 1])$。 + +由于 $f[i][j]$ 的值与 $f[i + 1][j - 1]$, $f[i + 1][j]$, $f[i][j - 1]$ 有关,所以我们应该从大到小枚举 $i$,从小到大枚举 $j$。 + +答案即为 $f[0][n - 1]$。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为字符串 $s$ 的长度。 @@ -49,36 +59,36 @@ class Solution: def longestPalindromeSubseq(self, s: str) -> int: n = len(s) - dp = [[0] * n for _ in range(n)] + f = [[0] * n for _ in range(n)] for i in range(n): - dp[i][i] = 1 - for j in range(1, n): - for i in range(j - 1, -1, -1): + f[i][i] = 1 + for i in range(n - 1, -1, -1): + for j in range(i + 1, n): if s[i] == s[j]: - dp[i][j] = dp[i + 1][j - 1] + 2 + f[i][j] = f[i + 1][j - 1] + 2 else: - dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]) - return dp[0][-1] + f[i][j] = max(f[i + 1][j], f[i][j - 1]) + return f[0][-1] ``` ```java class Solution { public int longestPalindromeSubseq(String s) { int n = s.length(); - int[][] dp = new int[n][n]; + int[][] f = new int[n][n]; for (int i = 0; i < n; ++i) { - dp[i][i] = 1; + f[i][i] = 1; } - for (int j = 1; j < n; ++j) { - for (int i = j - 1; i >= 0; --i) { + for (int i = n - 1; i >= 0; --i) { + for (int j = i + 1; j < n; ++j) { if (s.charAt(i) == s.charAt(j)) { - dp[i][j] = dp[i + 1][j - 1] + 2; + f[i][j] = f[i + 1][j - 1] + 2; } else { - dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]); } } } - return dp[0][n - 1]; + return f[0][n - 1]; } } ``` @@ -88,20 +98,21 @@ class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(); - vector> dp(n, vector(n, 0)); + int f[n][n]; + memset(f, 0, sizeof(f)); for (int i = 0; i < n; ++i) { - dp[i][i] = 1; + f[i][i] = 1; } - for (int j = 1; j < n; ++j) { - for (int i = j - 1; i >= 0; --i) { + for (int i = n - 1; ~i; --i) { + for (int j = i + 1; j < n; ++j) { if (s[i] == s[j]) { - dp[i][j] = dp[i + 1][j - 1] + 2; + f[i][j] = f[i + 1][j - 1] + 2; } else { - dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); + f[i][j] = max(f[i + 1][j], f[i][j - 1]); } } } - return dp[0][n - 1]; + return f[0][n - 1]; } }; ``` @@ -109,21 +120,41 @@ public: ```go func longestPalindromeSubseq(s string) int { n := len(s) - dp := make([][]int, n) - for i := 0; i < n; i++ { - dp[i] = make([]int, n) - dp[i][i] = 1 + f := make([][]int, n) + for i := range f { + f[i] = make([]int, n) + f[i][i] = 1 } - for j := 1; j < n; j++ { - for i := j - 1; i >= 0; i-- { + for i := n - 2; i >= 0; i-- { + for j := i + 1; j < n; j++ { if s[i] == s[j] { - dp[i][j] = dp[i+1][j-1] + 2 + f[i][j] = f[i+1][j-1] + 2 } else { - dp[i][j] = max(dp[i+1][j], dp[i][j-1]) + f[i][j] = max(f[i+1][j], f[i][j-1]) } } } - return dp[0][n-1] + return f[0][n-1] +} +``` + +```ts +function longestPalindromeSubseq(s: string): number { + const n = s.length; + const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0)); + for (let i = 0; i < n; ++i) { + f[i][i] = 1; + } + for (let i = n - 2; ~i; --i) { + for (let j = i + 1; j < n; ++j) { + if (s[i] === s[j]) { + f[i][j] = f[i + 1][j - 1] + 2; + } else { + f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]); + } + } + } + return f[0][n - 1]; } ``` diff --git a/solution/0500-0599/0516.Longest Palindromic Subsequence/README_EN.md b/solution/0500-0599/0516.Longest Palindromic Subsequence/README_EN.md index ef6eef33f1087..f86b65610c584 100644 --- a/solution/0500-0599/0516.Longest Palindromic Subsequence/README_EN.md +++ b/solution/0500-0599/0516.Longest Palindromic Subsequence/README_EN.md @@ -37,7 +37,17 @@ ## Solutions -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j]$ as the length of the longest palindromic subsequence from the $i$-th character to the $j$-th character in string $s$. Initially, $f[i][i] = 1$, and the values of other positions are all $0$. + +If $s[i] = s[j]$, then $f[i][j] = f[i + 1][j - 1] + 2$; otherwise, $f[i][j] = \max(f[i + 1][j], f[i][j - 1])$. + +Since the value of $f[i][j]$ is related to $f[i + 1][j - 1]$, $f[i + 1][j]$, and $f[i][j - 1]$, we should enumerate $i$ from large to small, and enumerate $j$ from small to large. + +The answer is $f[0][n - 1]$. + +The time complexity is $O(n^2)$, and the space complexity is $O(n^2)$. Where $n$ is the length of the string $s$. @@ -45,36 +55,36 @@ class Solution: def longestPalindromeSubseq(self, s: str) -> int: n = len(s) - dp = [[0] * n for _ in range(n)] + f = [[0] * n for _ in range(n)] for i in range(n): - dp[i][i] = 1 - for j in range(1, n): - for i in range(j - 1, -1, -1): + f[i][i] = 1 + for i in range(n - 1, -1, -1): + for j in range(i + 1, n): if s[i] == s[j]: - dp[i][j] = dp[i + 1][j - 1] + 2 + f[i][j] = f[i + 1][j - 1] + 2 else: - dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]) - return dp[0][-1] + f[i][j] = max(f[i + 1][j], f[i][j - 1]) + return f[0][-1] ``` ```java class Solution { public int longestPalindromeSubseq(String s) { int n = s.length(); - int[][] dp = new int[n][n]; + int[][] f = new int[n][n]; for (int i = 0; i < n; ++i) { - dp[i][i] = 1; + f[i][i] = 1; } - for (int j = 1; j < n; ++j) { - for (int i = j - 1; i >= 0; --i) { + for (int i = n - 1; i >= 0; --i) { + for (int j = i + 1; j < n; ++j) { if (s.charAt(i) == s.charAt(j)) { - dp[i][j] = dp[i + 1][j - 1] + 2; + f[i][j] = f[i + 1][j - 1] + 2; } else { - dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]); } } } - return dp[0][n - 1]; + return f[0][n - 1]; } } ``` @@ -84,20 +94,21 @@ class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(); - vector> dp(n, vector(n, 0)); + int f[n][n]; + memset(f, 0, sizeof(f)); for (int i = 0; i < n; ++i) { - dp[i][i] = 1; + f[i][i] = 1; } - for (int j = 1; j < n; ++j) { - for (int i = j - 1; i >= 0; --i) { + for (int i = n - 1; ~i; --i) { + for (int j = i + 1; j < n; ++j) { if (s[i] == s[j]) { - dp[i][j] = dp[i + 1][j - 1] + 2; + f[i][j] = f[i + 1][j - 1] + 2; } else { - dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); + f[i][j] = max(f[i + 1][j], f[i][j - 1]); } } } - return dp[0][n - 1]; + return f[0][n - 1]; } }; ``` @@ -105,21 +116,41 @@ public: ```go func longestPalindromeSubseq(s string) int { n := len(s) - dp := make([][]int, n) - for i := 0; i < n; i++ { - dp[i] = make([]int, n) - dp[i][i] = 1 + f := make([][]int, n) + for i := range f { + f[i] = make([]int, n) + f[i][i] = 1 } - for j := 1; j < n; j++ { - for i := j - 1; i >= 0; i-- { + for i := n - 2; i >= 0; i-- { + for j := i + 1; j < n; j++ { if s[i] == s[j] { - dp[i][j] = dp[i+1][j-1] + 2 + f[i][j] = f[i+1][j-1] + 2 } else { - dp[i][j] = max(dp[i+1][j], dp[i][j-1]) + f[i][j] = max(f[i+1][j], f[i][j-1]) } } } - return dp[0][n-1] + return f[0][n-1] +} +``` + +```ts +function longestPalindromeSubseq(s: string): number { + const n = s.length; + const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0)); + for (let i = 0; i < n; ++i) { + f[i][i] = 1; + } + for (let i = n - 2; ~i; --i) { + for (let j = i + 1; j < n; ++j) { + if (s[i] === s[j]) { + f[i][j] = f[i + 1][j - 1] + 2; + } else { + f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]); + } + } + } + return f[0][n - 1]; } ``` diff --git a/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.cpp b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.cpp index 07e73a16b549d..c4a879a9f3a09 100644 --- a/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.cpp +++ b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.cpp @@ -2,19 +2,20 @@ class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(); - vector> dp(n, vector(n, 0)); + int f[n][n]; + memset(f, 0, sizeof(f)); for (int i = 0; i < n; ++i) { - dp[i][i] = 1; + f[i][i] = 1; } - for (int j = 1; j < n; ++j) { - for (int i = j - 1; i >= 0; --i) { + for (int i = n - 1; ~i; --i) { + for (int j = i + 1; j < n; ++j) { if (s[i] == s[j]) { - dp[i][j] = dp[i + 1][j - 1] + 2; + f[i][j] = f[i + 1][j - 1] + 2; } else { - dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); + f[i][j] = max(f[i + 1][j], f[i][j - 1]); } } } - return dp[0][n - 1]; + return f[0][n - 1]; } }; \ No newline at end of file diff --git a/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.go b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.go index bde431c343b3b..96f369655249c 100644 --- a/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.go +++ b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.go @@ -1,18 +1,18 @@ func longestPalindromeSubseq(s string) int { n := len(s) - dp := make([][]int, n) - for i := 0; i < n; i++ { - dp[i] = make([]int, n) - dp[i][i] = 1 + f := make([][]int, n) + for i := range f { + f[i] = make([]int, n) + f[i][i] = 1 } - for j := 1; j < n; j++ { - for i := j - 1; i >= 0; i-- { + for i := n - 2; i >= 0; i-- { + for j := i + 1; j < n; j++ { if s[i] == s[j] { - dp[i][j] = dp[i+1][j-1] + 2 + f[i][j] = f[i+1][j-1] + 2 } else { - dp[i][j] = max(dp[i+1][j], dp[i][j-1]) + f[i][j] = max(f[i+1][j], f[i][j-1]) } } } - return dp[0][n-1] + return f[0][n-1] } \ No newline at end of file diff --git a/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.java b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.java index 8eab558cbe875..7361d420477a1 100644 --- a/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.java +++ b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.java @@ -1,19 +1,19 @@ class Solution { public int longestPalindromeSubseq(String s) { int n = s.length(); - int[][] dp = new int[n][n]; + int[][] f = new int[n][n]; for (int i = 0; i < n; ++i) { - dp[i][i] = 1; + f[i][i] = 1; } - for (int j = 1; j < n; ++j) { - for (int i = j - 1; i >= 0; --i) { + for (int i = n - 1; i >= 0; --i) { + for (int j = i + 1; j < n; ++j) { if (s.charAt(i) == s.charAt(j)) { - dp[i][j] = dp[i + 1][j - 1] + 2; + f[i][j] = f[i + 1][j - 1] + 2; } else { - dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]); } } } - return dp[0][n - 1]; + return f[0][n - 1]; } } \ No newline at end of file diff --git a/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.ts b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.ts new file mode 100644 index 0000000000000..1755b94719659 --- /dev/null +++ b/solution/0500-0599/0516.Longest Palindromic Subsequence/Solution.ts @@ -0,0 +1,17 @@ +function longestPalindromeSubseq(s: string): number { + const n = s.length; + const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0)); + for (let i = 0; i < n; ++i) { + f[i][i] = 1; + } + for (let i = n - 2; ~i; --i) { + for (let j = i + 1; j < n; ++j) { + if (s[i] === s[j]) { + f[i][j] = f[i + 1][j - 1] + 2; + } else { + f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]); + } + } + } + return f[0][n - 1]; +} diff --git a/solution/0500-0599/0517.Super Washing Machines/README_EN.md b/solution/0500-0599/0517.Super Washing Machines/README_EN.md index 70b4c8cfd2f0d..2a91396d19c75 100644 --- a/solution/0500-0599/0517.Super Washing Machines/README_EN.md +++ b/solution/0500-0599/0517.Super Washing Machines/README_EN.md @@ -54,7 +54,24 @@ It's impossible to make all three washing machines have the same number of d ## Solutions -### Solution 1 +### Solution 1: Greedy + +If the total number of clothes in the washing machines cannot be divided evenly by the number of washing machines, it is impossible to make the number of clothes in each washing machine equal, so we directly return $-1$. + +Otherwise, suppose the total number of clothes in the washing machines is $s$, then the number of clothes in each washing machine will eventually become $k = s / n$. + +We define $a_i$ as the difference between the number of clothes in the $i$-th washing machine and $k$, that is, $a_i = \text{machines}[i] - k$. If $a_i > 0$, it means that the $i$-th washing machine has extra clothes and needs to pass them to the adjacent washing machine; if $a_i < 0$, it means that the $i$-th washing machine lacks clothes and needs to get them from the adjacent washing machine. + +We define the sum of the differences in the number of clothes in the first $i$ washing machines as $s_i = \sum_{j=0}^{i-1} a_j$. If we regard the first $i$ washing machines as one group and the remaining washing machines as another group. Then if $s_i$ is a positive number, it means that the first group of washing machines has extra clothes and needs to pass them to the second group of washing machines; if $s_i$ is a negative number, it means that the first group of washing machines lacks clothes and needs to get them from the second group of washing machines. + +Then there are the following two situations: + +1. The maximum number of times clothes need to be moved between the two groups is $\max_{i=0}^{n-1} \lvert s_i \rvert$; +1. A washing machine in the group has too many clothes and needs to move clothes to both sides, the maximum number of times clothes need to be moved is $\max_{i=0}^{n-1} a_i$. + +We take the maximum of the two. + +The time complexity is $O(n)$, where $n$ is the number of washing machines. The space complexity is $O(1)$. diff --git a/solution/CONTEST_README.md b/solution/CONTEST_README.md index f49b377de80b5..d6b8b5056f0b0 100644 --- a/solution/CONTEST_README.md +++ b/solution/CONTEST_README.md @@ -18,7 +18,7 @@ ## 赛后估分网站 -- https://lccn.lbao.site +如果你想在比赛结束后估算自己的积分变化,可以访问网站 [LeetCode Contest Rating Predictor](https://lccn.lbao.site/)。 ## 往期竞赛 diff --git a/solution/CONTEST_README_EN.md b/solution/CONTEST_README_EN.md index dea38caeb14c5..19951662a6225 100644 --- a/solution/CONTEST_README_EN.md +++ b/solution/CONTEST_README_EN.md @@ -21,7 +21,7 @@ For top 10 users (excluding LCCN users), your LeetCode ID will be colored orange ## Rating Predictor -Get your rating changes right after the completion of LeetCode contests, https://lccn.lbao.site +If you want to estimate your score changes after the contest ends, you can visit the website [LeetCode Contest Rating Predictor](https://lccn.lbao.site/). ## Past Contests