diff --git a/solution/0400-0499/0439.Ternary Expression Parser/README.md b/solution/0400-0499/0439.Ternary Expression Parser/README.md index 9950111198240..560580475a1e0 100644 --- a/solution/0400-0499/0439.Ternary Expression Parser/README.md +++ b/solution/0400-0499/0439.Ternary Expression Parser/README.md @@ -55,6 +55,19 @@ or "(F ? 1 : (T ? 4 : 5))" --> "(T ? 4 : 5)" --> "4" +**方法一:栈** + +我们从右到左遍历字符串 `expression`,对于当前遍历到的字符 $c$: + +- 如果 $c$ 是字符 `':'`,则跳过; +- 如果 $c$ 是字符 `'?'`,那么意味着下一个即将遍历到的字符是条件表达式的条件,我们用一个布尔变量 `cond` 标记; +- 如果 $c$ 的上一个遍历到的字符是 `'?'`,也即布尔变量 `cond` 为 `true`,那么我们判断当前字符 $c$ 是否为字符 `'T'`,如果是,那么我们要保留栈顶第一个元素,弹出栈顶第二个元素;否则,我们要保留栈顶第二个元素,弹出栈顶第一个元素。最后,将 `cond` 置为 `false`; +- 否则,我们将当前字符 $c$ 入栈。 + +最后,栈中只剩下一个元素,即为表达式的结果。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 `expression` 的长度。 + ### **Python3** @@ -62,7 +75,27 @@ or "(F ? 1 : (T ? 4 : 5))" --> "(T ? 4 : 5)" --> "4" ```python - +class Solution: + def parseTernary(self, expression: str) -> str: + stk = [] + cond = False + for c in expression[::-1]: + if c == ':': + continue + if c == '?': + cond = True + else: + if cond: + if c == 'T': + x = stk.pop() + stk.pop() + stk.append(x) + else: + stk.pop() + cond = False + else: + stk.append(c) + return stk[0] ``` ### **Java** @@ -70,7 +103,103 @@ or "(F ? 1 : (T ? 4 : 5))" --> "(T ? 4 : 5)" --> "4" ```java +class Solution { + public String parseTernary(String expression) { + Deque stk = new ArrayDeque<>(); + boolean cond = false; + for (int i = expression.length() - 1; i >= 0; --i) { + char c = expression.charAt(i); + if (c == ':') { + continue; + } + if (c == '?') { + cond = true; + } else { + if (cond) { + if (c == 'T') { + char x = stk.pop(); + stk.pop(); + stk.push(x); + } else { + stk.pop(); + } + cond = false; + } else { + stk.push(c); + } + } + } + return String.valueOf(stk.peek()); + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + string parseTernary(string expression) { + string stk; + bool cond = false; + reverse(expression.begin(), expression.end()); + for (char& c : expression) { + if (c == ':') { + continue; + } + if (c == '?') { + cond = true; + } else { + if (cond) { + if (c == 'T') { + char x = stk.back(); + stk.pop_back(); + stk.pop_back(); + stk.push_back(x); + } else { + stk.pop_back(); + } + cond = false; + } else { + stk.push_back(c); + } + } + } + return {stk[0]}; + } +}; +``` +### **Go** + +```go +func parseTernary(expression string) string { + stk := []byte{} + cond := false + for i := len(expression) - 1; i >= 0; i-- { + c := expression[i] + if c == ':' { + continue + } + if c == '?' { + cond = true + } else { + if cond { + if c == 'T' { + x := stk[len(stk)-1] + stk = stk[:len(stk)-2] + stk = append(stk, x) + } else { + stk = stk[:len(stk)-1] + } + cond = false + } else { + stk = append(stk, c) + } + } + } + return string(stk[0]) +} ``` ### **...** diff --git a/solution/0400-0499/0439.Ternary Expression Parser/README_EN.md b/solution/0400-0499/0439.Ternary Expression Parser/README_EN.md index 0eda2206f28be..7ed2e5ab9eb68 100644 --- a/solution/0400-0499/0439.Ternary Expression Parser/README_EN.md +++ b/solution/0400-0499/0439.Ternary Expression Parser/README_EN.md @@ -55,13 +55,129 @@ or "(F ? 1 : (T ? 4 : 5))" --> "(T ? 4 : 5)" --> " ### **Python3** ```python - +class Solution: + def parseTernary(self, expression: str) -> str: + stk = [] + cond = False + for c in expression[::-1]: + if c == ':': + continue + if c == '?': + cond = True + else: + if cond: + if c == 'T': + x = stk.pop() + stk.pop() + stk.append(x) + else: + stk.pop() + cond = False + else: + stk.append(c) + return stk[0] ``` ### **Java** ```java +class Solution { + public String parseTernary(String expression) { + Deque stk = new ArrayDeque<>(); + boolean cond = false; + for (int i = expression.length() - 1; i >= 0; --i) { + char c = expression.charAt(i); + if (c == ':') { + continue; + } + if (c == '?') { + cond = true; + } else { + if (cond) { + if (c == 'T') { + char x = stk.pop(); + stk.pop(); + stk.push(x); + } else { + stk.pop(); + } + cond = false; + } else { + stk.push(c); + } + } + } + return String.valueOf(stk.peek()); + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + string parseTernary(string expression) { + string stk; + bool cond = false; + reverse(expression.begin(), expression.end()); + for (char& c : expression) { + if (c == ':') { + continue; + } + if (c == '?') { + cond = true; + } else { + if (cond) { + if (c == 'T') { + char x = stk.back(); + stk.pop_back(); + stk.pop_back(); + stk.push_back(x); + } else { + stk.pop_back(); + } + cond = false; + } else { + stk.push_back(c); + } + } + } + return {stk[0]}; + } +}; +``` +### **Go** + +```go +func parseTernary(expression string) string { + stk := []byte{} + cond := false + for i := len(expression) - 1; i >= 0; i-- { + c := expression[i] + if c == ':' { + continue + } + if c == '?' { + cond = true + } else { + if cond { + if c == 'T' { + x := stk[len(stk)-1] + stk = stk[:len(stk)-2] + stk = append(stk, x) + } else { + stk = stk[:len(stk)-1] + } + cond = false + } else { + stk = append(stk, c) + } + } + } + return string(stk[0]) +} ``` ### **...** diff --git a/solution/0400-0499/0439.Ternary Expression Parser/Solution.cpp b/solution/0400-0499/0439.Ternary Expression Parser/Solution.cpp new file mode 100644 index 0000000000000..f2aba0bf3d9cd --- /dev/null +++ b/solution/0400-0499/0439.Ternary Expression Parser/Solution.cpp @@ -0,0 +1,31 @@ +class Solution { +public: + string parseTernary(string expression) { + string stk; + bool cond = false; + reverse(expression.begin(), expression.end()); + for (char& c : expression) { + if (c == ':') { + continue; + } + if (c == '?') { + cond = true; + } else { + if (cond) { + if (c == 'T') { + char x = stk.back(); + stk.pop_back(); + stk.pop_back(); + stk.push_back(x); + } else { + stk.pop_back(); + } + cond = false; + } else { + stk.push_back(c); + } + } + } + return {stk[0]}; + } +}; \ No newline at end of file diff --git a/solution/0400-0499/0439.Ternary Expression Parser/Solution.go b/solution/0400-0499/0439.Ternary Expression Parser/Solution.go new file mode 100644 index 0000000000000..ebacc3bd198ed --- /dev/null +++ b/solution/0400-0499/0439.Ternary Expression Parser/Solution.go @@ -0,0 +1,27 @@ +func parseTernary(expression string) string { + stk := []byte{} + cond := false + for i := len(expression) - 1; i >= 0; i-- { + c := expression[i] + if c == ':' { + continue + } + if c == '?' { + cond = true + } else { + if cond { + if c == 'T' { + x := stk[len(stk)-1] + stk = stk[:len(stk)-2] + stk = append(stk, x) + } else { + stk = stk[:len(stk)-1] + } + cond = false + } else { + stk = append(stk, c) + } + } + } + return string(stk[0]) +} \ No newline at end of file diff --git a/solution/0400-0499/0439.Ternary Expression Parser/Solution.java b/solution/0400-0499/0439.Ternary Expression Parser/Solution.java new file mode 100644 index 0000000000000..b02d68942ed77 --- /dev/null +++ b/solution/0400-0499/0439.Ternary Expression Parser/Solution.java @@ -0,0 +1,29 @@ +class Solution { + public String parseTernary(String expression) { + Deque stk = new ArrayDeque<>(); + boolean cond = false; + for (int i = expression.length() - 1; i >= 0; --i) { + char c = expression.charAt(i); + if (c == ':') { + continue; + } + if (c == '?') { + cond = true; + } else { + if (cond) { + if (c == 'T') { + char x = stk.pop(); + stk.pop(); + stk.push(x); + } else { + stk.pop(); + } + cond = false; + } else { + stk.push(c); + } + } + } + return String.valueOf(stk.peek()); + } +} \ No newline at end of file diff --git a/solution/0400-0499/0439.Ternary Expression Parser/Solution.py b/solution/0400-0499/0439.Ternary Expression Parser/Solution.py new file mode 100644 index 0000000000000..60ea1aa2e7eb8 --- /dev/null +++ b/solution/0400-0499/0439.Ternary Expression Parser/Solution.py @@ -0,0 +1,21 @@ +class Solution: + def parseTernary(self, expression: str) -> str: + stk = [] + cond = False + for c in expression[::-1]: + if c == ':': + continue + if c == '?': + cond = True + else: + if cond: + if c == 'T': + x = stk.pop() + stk.pop() + stk.append(x) + else: + stk.pop() + cond = False + else: + stk.append(c) + return stk[0] diff --git a/solution/0800-0899/0831.Masking Personal Information/README.md b/solution/0800-0899/0831.Masking Personal Information/README.md index 2131f9cd28873..8cf81785af5c5 100644 --- a/solution/0800-0899/0831.Masking Personal Information/README.md +++ b/solution/0800-0899/0831.Masking Personal Information/README.md @@ -227,6 +227,30 @@ func maskPII(s string) string { } ``` +### **TypeScript** + +```ts +function maskPII(s: string): string { + const i = s.indexOf('@'); + if (i !== -1) { + let ans = s[0].toLowerCase() + '*****'; + for (let j = i - 1; j < s.length; ++j) { + ans += s.charAt(j).toLowerCase(); + } + return ans; + } + let t = ''; + for (const c of s) { + if (/\d/.test(c)) { + t += c; + } + } + const cnt = t.length - 10; + const suf = `***-***-${t.substring(t.length - 4)}`; + return cnt === 0 ? suf : `+${'*'.repeat(cnt)}-${suf}`; +} +``` + ### **...** ``` diff --git a/solution/0800-0899/0831.Masking Personal Information/README_EN.md b/solution/0800-0899/0831.Masking Personal Information/README_EN.md index cb585c6c79d86..169d096a6674a 100644 --- a/solution/0800-0899/0831.Masking Personal Information/README_EN.md +++ b/solution/0800-0899/0831.Masking Personal Information/README_EN.md @@ -196,6 +196,30 @@ func maskPII(s string) string { } ``` +### **TypeScript** + +```ts +function maskPII(s: string): string { + const i = s.indexOf('@'); + if (i !== -1) { + let ans = s[0].toLowerCase() + '*****'; + for (let j = i - 1; j < s.length; ++j) { + ans += s.charAt(j).toLowerCase(); + } + return ans; + } + let t = ''; + for (const c of s) { + if (/\d/.test(c)) { + t += c; + } + } + const cnt = t.length - 10; + const suf = `***-***-${t.substring(t.length - 4)}`; + return cnt === 0 ? suf : `+${'*'.repeat(cnt)}-${suf}`; +} +``` + ### **...** ``` diff --git a/solution/0800-0899/0831.Masking Personal Information/Solution.ts b/solution/0800-0899/0831.Masking Personal Information/Solution.ts new file mode 100644 index 0000000000000..6b3c14021238e --- /dev/null +++ b/solution/0800-0899/0831.Masking Personal Information/Solution.ts @@ -0,0 +1,19 @@ +function maskPII(s: string): string { + const i = s.indexOf('@'); + if (i !== -1) { + let ans = s[0].toLowerCase() + '*****'; + for (let j = i - 1; j < s.length; ++j) { + ans += s.charAt(j).toLowerCase(); + } + return ans; + } + let t = ''; + for (const c of s) { + if (/\d/.test(c)) { + t += c; + } + } + const cnt = t.length - 10; + const suf = `***-***-${t.substring(t.length - 4)}`; + return cnt === 0 ? suf : `+${'*'.repeat(cnt)}-${suf}`; +} diff --git a/solution/0800-0899/0836.Rectangle Overlap/README.md b/solution/0800-0899/0836.Rectangle Overlap/README.md index 8885ace81e0eb..8ea99ed24e464 100644 --- a/solution/0800-0899/0836.Rectangle Overlap/README.md +++ b/solution/0800-0899/0836.Rectangle Overlap/README.md @@ -50,6 +50,21 @@ +**方法一:判断不重叠的情况** + +我们记矩形 $rec1$ 的坐标点为 $(x_1, y_1, x_2, y_2)$,矩形 $rec2$ 的坐标点为 $(x_3, y_3, x_4, y_4)$。 + +那么当满足以下任一条件时,矩形 $rec1$ 和 $rec2$ 不重叠: + +- 满足 $y_3 \geq y_2$,即 $rec2$ 在 $rec1$ 的上方; +- 满足 $y_4 \leq y_1$,即 $rec2$ 在 $rec1$ 的下方; +- 满足 $x_3 \geq x_2$,即 $rec2$ 在 $rec1$ 的右方; +- 满足 $x_4 \leq x_1$,即 $rec2$ 在 $rec1$ 的左方。 + +当以上条件都不满足时,矩形 $rec1$ 和 $rec2$ 重叠。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 + ### **Python3** @@ -57,7 +72,11 @@ ```python - +class Solution: + def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool: + x1, y1, x2, y2 = rec1 + x3, y3, x4, y4 = rec2 + return not (y3 >= y2 or y4 <= y1 or x3 >= x2 or x4 <= x1) ``` ### **Java** @@ -65,7 +84,36 @@ ```java +class Solution { + public boolean isRectangleOverlap(int[] rec1, int[] rec2) { + int x1 = rec1[0], y1 = rec1[1], x2 = rec1[2], y2 = rec1[3]; + int x3 = rec2[0], y3 = rec2[1], x4 = rec2[2], y4 = rec2[3]; + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1); + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + bool isRectangleOverlap(vector& rec1, vector& rec2) { + int x1 = rec1[0], y1 = rec1[1], x2 = rec1[2], y2 = rec1[3]; + int x3 = rec2[0], y3 = rec2[1], x4 = rec2[2], y4 = rec2[3]; + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1); + } +}; +``` + +### **Go** +```go +func isRectangleOverlap(rec1 []int, rec2 []int) bool { + x1, y1, x2, y2 := rec1[0], rec1[1], rec1[2], rec1[3] + x3, y3, x4, y4 := rec2[0], rec2[1], rec2[2], rec2[3] + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1) +} ``` ### **...** diff --git a/solution/0800-0899/0836.Rectangle Overlap/README_EN.md b/solution/0800-0899/0836.Rectangle Overlap/README_EN.md index b8e0d1dc5cc96..ccbab1255bbac 100644 --- a/solution/0800-0899/0836.Rectangle Overlap/README_EN.md +++ b/solution/0800-0899/0836.Rectangle Overlap/README_EN.md @@ -38,13 +38,46 @@ ### **Python3** ```python - +class Solution: + def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool: + x1, y1, x2, y2 = rec1 + x3, y3, x4, y4 = rec2 + return not (y3 >= y2 or y4 <= y1 or x3 >= x2 or x4 <= x1) ``` ### **Java** ```java +class Solution { + public boolean isRectangleOverlap(int[] rec1, int[] rec2) { + int x1 = rec1[0], y1 = rec1[1], x2 = rec1[2], y2 = rec1[3]; + int x3 = rec2[0], y3 = rec2[1], x4 = rec2[2], y4 = rec2[3]; + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1); + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + bool isRectangleOverlap(vector& rec1, vector& rec2) { + int x1 = rec1[0], y1 = rec1[1], x2 = rec1[2], y2 = rec1[3]; + int x3 = rec2[0], y3 = rec2[1], x4 = rec2[2], y4 = rec2[3]; + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1); + } +}; +``` + +### **Go** +```go +func isRectangleOverlap(rec1 []int, rec2 []int) bool { + x1, y1, x2, y2 := rec1[0], rec1[1], rec1[2], rec1[3] + x3, y3, x4, y4 := rec2[0], rec2[1], rec2[2], rec2[3] + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1) +} ``` ### **...** diff --git a/solution/0800-0899/0836.Rectangle Overlap/Solution.cpp b/solution/0800-0899/0836.Rectangle Overlap/Solution.cpp index 8d6922d72fd2c..04554d400ba0e 100644 --- a/solution/0800-0899/0836.Rectangle Overlap/Solution.cpp +++ b/solution/0800-0899/0836.Rectangle Overlap/Solution.cpp @@ -1,14 +1,8 @@ class Solution { public: bool isRectangleOverlap(vector& rec1, vector& rec2) { - int l1 = rec1[1], u1 = rec1[0], r1 = rec1[3], d1 = rec1[2]; - int l2 = rec2[1], u2 = rec2[0], r2 = rec2[3], d2 = rec2[2]; - - //printf("1: (%d,%d), (%d,%d)\n", l1, u1, r1, d1) ; - //printf("2: (%d,%d), (%d,%d)\n", l2, u2, r2, d2) ; - - if (l1 < r2 && u1 < d2 && l2 < r1 && u2 < d1) - return true; - return false; + int x1 = rec1[0], y1 = rec1[1], x2 = rec1[2], y2 = rec1[3]; + int x3 = rec2[0], y3 = rec2[1], x4 = rec2[2], y4 = rec2[3]; + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1); } }; \ No newline at end of file diff --git a/solution/0800-0899/0836.Rectangle Overlap/Solution.go b/solution/0800-0899/0836.Rectangle Overlap/Solution.go new file mode 100644 index 0000000000000..608e610335810 --- /dev/null +++ b/solution/0800-0899/0836.Rectangle Overlap/Solution.go @@ -0,0 +1,5 @@ +func isRectangleOverlap(rec1 []int, rec2 []int) bool { + x1, y1, x2, y2 := rec1[0], rec1[1], rec1[2], rec1[3] + x3, y3, x4, y4 := rec2[0], rec2[1], rec2[2], rec2[3] + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1) +} \ No newline at end of file diff --git a/solution/0800-0899/0836.Rectangle Overlap/Solution.java b/solution/0800-0899/0836.Rectangle Overlap/Solution.java new file mode 100644 index 0000000000000..819fda1eae215 --- /dev/null +++ b/solution/0800-0899/0836.Rectangle Overlap/Solution.java @@ -0,0 +1,7 @@ +class Solution { + public boolean isRectangleOverlap(int[] rec1, int[] rec2) { + int x1 = rec1[0], y1 = rec1[1], x2 = rec1[2], y2 = rec1[3]; + int x3 = rec2[0], y3 = rec2[1], x4 = rec2[2], y4 = rec2[3]; + return !(y3 >= y2 || y4 <= y1 || x3 >= x2 || x4 <= x1); + } +} \ No newline at end of file diff --git a/solution/0800-0899/0836.Rectangle Overlap/Solution.py b/solution/0800-0899/0836.Rectangle Overlap/Solution.py new file mode 100644 index 0000000000000..7abf612583c69 --- /dev/null +++ b/solution/0800-0899/0836.Rectangle Overlap/Solution.py @@ -0,0 +1,5 @@ +class Solution: + def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool: + x1, y1, x2, y2 = rec1 + x3, y3, x4, y4 = rec2 + return not (y3 >= y2 or y4 <= y1 or x3 >= x2 or x4 <= x1) diff --git a/solution/0800-0899/0844.Backspace String Compare/README.md b/solution/0800-0899/0844.Backspace String Compare/README.md index 557abd62b3b90..4627c5217a502 100644 --- a/solution/0800-0899/0844.Backspace String Compare/README.md +++ b/solution/0800-0899/0844.Backspace String Compare/README.md @@ -58,7 +58,13 @@ **方法一:双指针** -时间复杂度 O(len(s) + len(t)),空间复杂度 O(1)。 +我们用双指针 $i$ 和 $j$ 分别指向字符串 $s$ 和 $t$ 的末尾。 + +每次向前移动一个字符,如果当前字符是退格符,则跳过当前字符,同时退格符的数量加一,如果当前字符不是退格符,则判断退格符的数量,如果退格符的数量大于 $0$,则跳过当前字符,同时退格符的数量减一,如果退格符的数量等于 $0$,那么该字符需要进行比较。 + +我们每次找到两个字符串中需要比较的字符,然后进行比较,如果两个字符不相等,则返回 $false$,如果遍历完两个字符串,都没有发现不相等的字符,则返回 $true$。 + +时间复杂度 $O(m + n)$,空间复杂度 $O(1)$。其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度。 diff --git a/solution/0800-0899/0847.Shortest Path Visiting All Nodes/README.md b/solution/0800-0899/0847.Shortest Path Visiting All Nodes/README.md index bc8b7a4ed45fa..68cb91a4f1a16 100644 --- a/solution/0800-0899/0847.Shortest Path Visiting All Nodes/README.md +++ b/solution/0800-0899/0847.Shortest Path Visiting All Nodes/README.md @@ -51,6 +51,8 @@ +**方法一:BFS(A\* 算法)** + 因为每条边权值一样,所以用 BFS 就能得出最短路径,过程中可以用**状态压缩**记录节点的访问情况。另外,同一个节点 u 以及对应的节点访问情况需要保证只被搜索过一次,因此可以用 `vis(u, state)` 表示是否已经被搜索过,防止无效的重复搜索。 本题也属于 BFS 最小步数模型,可以使用 A\* 算法优化搜索。 diff --git a/solution/0800-0899/0851.Loud and Rich/README.md b/solution/0800-0899/0851.Loud and Rich/README.md index da50f35b73142..ea165526c9331 100644 --- a/solution/0800-0899/0851.Loud and Rich/README.md +++ b/solution/0800-0899/0851.Loud and Rich/README.md @@ -57,9 +57,13 @@ answer[7] = 7, -根据 richer 关系构建有向图,如果 a 比 b 有钱,那么连一条从 b 到 a 的有向边,最终构建出一个有向无环图。 +**方法一:DFS** -我们知道,从图的任一点 i 出发,沿着有向边所能访问到的点,都比 i 更有钱。DFS 深搜即可。 +我们先用邻接表 $g$ 存储 $richer$ 数组中的信息,其中 $g[i]$ 表示所有比 $i$ 更有钱的人的集合。 + +然后对于每个人 $i$,我们用 DFS 遍历所有比 $i$ 更有钱的人,找到其中安静值最小的人,即为答案。 + +时间复杂度 $O(m + n)$,空间复杂度 $O(m + n)$。其中 $m$ 和 $n$ 分别为 $richer$ 数组和 $quiet$ 数组的长度。 @@ -70,13 +74,7 @@ answer[7] = 7, ```python class Solution: def loudAndRich(self, richer: List[List[int]], quiet: List[int]) -> List[int]: - n = len(quiet) - g = defaultdict(list) - for a, b in richer: - g[b].append(a) - ans = [-1] * n - - def dfs(i): + def dfs(i: int): if ans[i] != -1: return ans[i] = i @@ -85,6 +83,11 @@ class Solution: if quiet[ans[j]] < quiet[ans[i]]: ans[i] = ans[j] + g = defaultdict(list) + for a, b in richer: + g[b].append(a) + n = len(quiet) + ans = [-1] * n for i in range(n): dfs(i) return ans @@ -96,19 +99,22 @@ class Solution: ```java class Solution { - private Map> g; + private List[] g; + private int n; private int[] quiet; private int[] ans; public int[] loudAndRich(int[][] richer, int[] quiet) { - g = new HashMap<>(); + n = quiet.length; this.quiet = quiet; - ans = new int[quiet.length]; + g = new List[n]; + ans = new int[n]; Arrays.fill(ans, -1); - for (int[] r : richer) { - g.computeIfAbsent(r[1], k -> new ArrayList<>()).add(r[0]); + Arrays.setAll(g, k -> new ArrayList<>()); + for (var r : richer) { + g[r[1]].add(r[0]); } - for (int i = 0; i < quiet.length; ++i) { + for (int i = 0; i < n; ++i) { dfs(i); } return ans; @@ -119,10 +125,7 @@ class Solution { return; } ans[i] = i; - if (!g.containsKey(i)) { - return; - } - for (int j : g.get(i)) { + for (int j : g[i]) { dfs(j); if (quiet[ans[j]] < quiet[ans[i]]) { ans[i] = ans[j]; @@ -140,18 +143,25 @@ public: vector loudAndRich(vector>& richer, vector& quiet) { int n = quiet.size(); vector> g(n); - for (auto& r : richer) g[r[1]].push_back(r[0]); + for (auto& r : richer) { + g[r[1]].push_back(r[0]); + } vector ans(n, -1); function dfs = [&](int i) { - if (ans[i] != -1) return; + if (ans[i] != -1) { + return; + } ans[i] = i; for (int j : g[i]) { dfs(j); - if (quiet[ans[j]] < quiet[ans[i]]) ans[i] = ans[j]; + if (quiet[ans[j]] < quiet[ans[i]]) { + ans[i] = ans[j]; + } } }; - for (int i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { dfs(i); + } return ans; } }; @@ -161,35 +171,62 @@ public: ```go func loudAndRich(richer [][]int, quiet []int) []int { - n := len(quiet) - ans := make([]int, n) - g := make([][]int, n) - for i := 0; i < n; i++ { - ans[i] = -1 - g[i] = make([]int, 0) - } - for _, r := range richer { - g[r[1]] = append(g[r[1]], r[0]) - } + n := len(quiet) + g := make([][]int, n) + ans := make([]int, n) + for i := range g { + ans[i] = -1 + } + for _, r := range richer { + a, b := r[0], r[1] + g[b] = append(g[b], a) + } + var dfs func(int) + dfs = func(i int) { + if ans[i] != -1 { + return + } + ans[i] = i + for _, j := range g[i] { + dfs(j) + if quiet[ans[j]] < quiet[ans[i]] { + ans[i] = ans[j] + } + } + } + for i := range ans { + dfs(i) + } + return ans +} +``` - var dfs func(i int) - dfs = func(i int) { - if ans[i] != - 1 { - return +### **TypeScript** + +```ts +function loudAndRich(richer: number[][], quiet: number[]): number[] { + const n = quiet.length; + const g: number[][] = new Array(n).fill(0).map(() => []); + for (const [a, b] of richer) { + g[b].push(a); + } + const ans: number[] = new Array(n).fill(-1); + const dfs = (i: number) => { + if (ans[i] != -1) { + return ans; } - ans[i] = i - for _, j := range g[i] { - dfs(j) - if quiet[ans[j]] < quiet[ans[i]] { - ans[i] = ans[j] + ans[i] = i; + for (const j of g[i]) { + dfs(j); + if (quiet[ans[j]] < quiet[ans[i]]) { + ans[i] = ans[j]; } } + }; + for (let i = 0; i < n; ++i) { + dfs(i); } - - for i := 0; i < n; i++ { - dfs(i) - } - return ans + return ans; } ``` diff --git a/solution/0800-0899/0851.Loud and Rich/README_EN.md b/solution/0800-0899/0851.Loud and Rich/README_EN.md index 716f0dd735a30..34b24052a89ae 100644 --- a/solution/0800-0899/0851.Loud and Rich/README_EN.md +++ b/solution/0800-0899/0851.Loud and Rich/README_EN.md @@ -56,13 +56,7 @@ The other answers can be filled out with similar reasoning. ```python class Solution: def loudAndRich(self, richer: List[List[int]], quiet: List[int]) -> List[int]: - n = len(quiet) - g = defaultdict(list) - for a, b in richer: - g[b].append(a) - ans = [-1] * n - - def dfs(i): + def dfs(i: int): if ans[i] != -1: return ans[i] = i @@ -71,6 +65,11 @@ class Solution: if quiet[ans[j]] < quiet[ans[i]]: ans[i] = ans[j] + g = defaultdict(list) + for a, b in richer: + g[b].append(a) + n = len(quiet) + ans = [-1] * n for i in range(n): dfs(i) return ans @@ -80,19 +79,22 @@ class Solution: ```java class Solution { - private Map> g; + private List[] g; + private int n; private int[] quiet; private int[] ans; public int[] loudAndRich(int[][] richer, int[] quiet) { - g = new HashMap<>(); + n = quiet.length; this.quiet = quiet; - ans = new int[quiet.length]; + g = new List[n]; + ans = new int[n]; Arrays.fill(ans, -1); - for (int[] r : richer) { - g.computeIfAbsent(r[1], k -> new ArrayList<>()).add(r[0]); + Arrays.setAll(g, k -> new ArrayList<>()); + for (var r : richer) { + g[r[1]].add(r[0]); } - for (int i = 0; i < quiet.length; ++i) { + for (int i = 0; i < n; ++i) { dfs(i); } return ans; @@ -103,10 +105,7 @@ class Solution { return; } ans[i] = i; - if (!g.containsKey(i)) { - return; - } - for (int j : g.get(i)) { + for (int j : g[i]) { dfs(j); if (quiet[ans[j]] < quiet[ans[i]]) { ans[i] = ans[j]; @@ -124,18 +123,25 @@ public: vector loudAndRich(vector>& richer, vector& quiet) { int n = quiet.size(); vector> g(n); - for (auto& r : richer) g[r[1]].push_back(r[0]); + for (auto& r : richer) { + g[r[1]].push_back(r[0]); + } vector ans(n, -1); function dfs = [&](int i) { - if (ans[i] != -1) return; + if (ans[i] != -1) { + return; + } ans[i] = i; for (int j : g[i]) { dfs(j); - if (quiet[ans[j]] < quiet[ans[i]]) ans[i] = ans[j]; + if (quiet[ans[j]] < quiet[ans[i]]) { + ans[i] = ans[j]; + } } }; - for (int i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { dfs(i); + } return ans; } }; @@ -145,35 +151,62 @@ public: ```go func loudAndRich(richer [][]int, quiet []int) []int { - n := len(quiet) - ans := make([]int, n) - g := make([][]int, n) - for i := 0; i < n; i++ { - ans[i] = -1 - g[i] = make([]int, 0) - } - for _, r := range richer { - g[r[1]] = append(g[r[1]], r[0]) - } + n := len(quiet) + g := make([][]int, n) + ans := make([]int, n) + for i := range g { + ans[i] = -1 + } + for _, r := range richer { + a, b := r[0], r[1] + g[b] = append(g[b], a) + } + var dfs func(int) + dfs = func(i int) { + if ans[i] != -1 { + return + } + ans[i] = i + for _, j := range g[i] { + dfs(j) + if quiet[ans[j]] < quiet[ans[i]] { + ans[i] = ans[j] + } + } + } + for i := range ans { + dfs(i) + } + return ans +} +``` + +### **TypeScript** - var dfs func(i int) - dfs = func(i int) { - if ans[i] != - 1 { - return +```ts +function loudAndRich(richer: number[][], quiet: number[]): number[] { + const n = quiet.length; + const g: number[][] = new Array(n).fill(0).map(() => []); + for (const [a, b] of richer) { + g[b].push(a); + } + const ans: number[] = new Array(n).fill(-1); + const dfs = (i: number) => { + if (ans[i] != -1) { + return ans; } - ans[i] = i - for _, j := range g[i] { - dfs(j) - if quiet[ans[j]] < quiet[ans[i]] { - ans[i] = ans[j] + ans[i] = i; + for (const j of g[i]) { + dfs(j); + if (quiet[ans[j]] < quiet[ans[i]]) { + ans[i] = ans[j]; } } + }; + for (let i = 0; i < n; ++i) { + dfs(i); } - - for i := 0; i < n; i++ { - dfs(i) - } - return ans + return ans; } ``` diff --git a/solution/0800-0899/0851.Loud and Rich/Solution.cpp b/solution/0800-0899/0851.Loud and Rich/Solution.cpp index 074f52c0dd588..ba5ac1f27c2fd 100644 --- a/solution/0800-0899/0851.Loud and Rich/Solution.cpp +++ b/solution/0800-0899/0851.Loud and Rich/Solution.cpp @@ -3,18 +3,25 @@ class Solution { vector loudAndRich(vector>& richer, vector& quiet) { int n = quiet.size(); vector> g(n); - for (auto& r : richer) g[r[1]].push_back(r[0]); + for (auto& r : richer) { + g[r[1]].push_back(r[0]); + } vector ans(n, -1); function dfs = [&](int i) { - if (ans[i] != -1) return; + if (ans[i] != -1) { + return; + } ans[i] = i; for (int j : g[i]) { dfs(j); - if (quiet[ans[j]] < quiet[ans[i]]) ans[i] = ans[j]; + if (quiet[ans[j]] < quiet[ans[i]]) { + ans[i] = ans[j]; + } } }; - for (int i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { dfs(i); + } return ans; } }; \ No newline at end of file diff --git a/solution/0800-0899/0851.Loud and Rich/Solution.go b/solution/0800-0899/0851.Loud and Rich/Solution.go index 94bd0fc2227b7..49d625aa1d9ac 100644 --- a/solution/0800-0899/0851.Loud and Rich/Solution.go +++ b/solution/0800-0899/0851.Loud and Rich/Solution.go @@ -1,31 +1,29 @@ func loudAndRich(richer [][]int, quiet []int) []int { - n := len(quiet) - ans := make([]int, n) - g := make([][]int, n) - for i := 0; i < n; i++ { - ans[i] = -1 - g[i] = make([]int, 0) - } - for _, r := range richer { - g[r[1]] = append(g[r[1]], r[0]) - } - - var dfs func(i int) - dfs = func(i int) { - if ans[i] != - 1 { - return - } - ans[i] = i - for _, j := range g[i] { - dfs(j) - if quiet[ans[j]] < quiet[ans[i]] { - ans[i] = ans[j] - } - } - } - - for i := 0; i < n; i++ { - dfs(i) - } - return ans + n := len(quiet) + g := make([][]int, n) + ans := make([]int, n) + for i := range g { + ans[i] = -1 + } + for _, r := range richer { + a, b := r[0], r[1] + g[b] = append(g[b], a) + } + var dfs func(int) + dfs = func(i int) { + if ans[i] != -1 { + return + } + ans[i] = i + for _, j := range g[i] { + dfs(j) + if quiet[ans[j]] < quiet[ans[i]] { + ans[i] = ans[j] + } + } + } + for i := range ans { + dfs(i) + } + return ans } \ No newline at end of file diff --git a/solution/0800-0899/0851.Loud and Rich/Solution.java b/solution/0800-0899/0851.Loud and Rich/Solution.java index 07fed19067d83..4f41f83ace232 100644 --- a/solution/0800-0899/0851.Loud and Rich/Solution.java +++ b/solution/0800-0899/0851.Loud and Rich/Solution.java @@ -1,17 +1,20 @@ class Solution { - private Map> g; + private List[] g; + private int n; private int[] quiet; private int[] ans; public int[] loudAndRich(int[][] richer, int[] quiet) { - g = new HashMap<>(); + n = quiet.length; this.quiet = quiet; - ans = new int[quiet.length]; + g = new List[n]; + ans = new int[n]; Arrays.fill(ans, -1); - for (int[] r : richer) { - g.computeIfAbsent(r[1], k -> new ArrayList<>()).add(r[0]); + Arrays.setAll(g, k -> new ArrayList<>()); + for (var r : richer) { + g[r[1]].add(r[0]); } - for (int i = 0; i < quiet.length; ++i) { + for (int i = 0; i < n; ++i) { dfs(i); } return ans; @@ -22,10 +25,7 @@ private void dfs(int i) { return; } ans[i] = i; - if (!g.containsKey(i)) { - return; - } - for (int j : g.get(i)) { + for (int j : g[i]) { dfs(j); if (quiet[ans[j]] < quiet[ans[i]]) { ans[i] = ans[j]; diff --git a/solution/0800-0899/0851.Loud and Rich/Solution.py b/solution/0800-0899/0851.Loud and Rich/Solution.py index db5be9101de98..f37c47903ac73 100644 --- a/solution/0800-0899/0851.Loud and Rich/Solution.py +++ b/solution/0800-0899/0851.Loud and Rich/Solution.py @@ -1,12 +1,6 @@ class Solution: def loudAndRich(self, richer: List[List[int]], quiet: List[int]) -> List[int]: - n = len(quiet) - g = defaultdict(list) - for a, b in richer: - g[b].append(a) - ans = [-1] * n - - def dfs(i): + def dfs(i: int): if ans[i] != -1: return ans[i] = i @@ -15,6 +9,11 @@ def dfs(i): if quiet[ans[j]] < quiet[ans[i]]: ans[i] = ans[j] + g = defaultdict(list) + for a, b in richer: + g[b].append(a) + n = len(quiet) + ans = [-1] * n for i in range(n): dfs(i) return ans diff --git a/solution/0800-0899/0851.Loud and Rich/Solution.ts b/solution/0800-0899/0851.Loud and Rich/Solution.ts new file mode 100644 index 0000000000000..05a873916c1aa --- /dev/null +++ b/solution/0800-0899/0851.Loud and Rich/Solution.ts @@ -0,0 +1,24 @@ +function loudAndRich(richer: number[][], quiet: number[]): number[] { + const n = quiet.length; + const g: number[][] = new Array(n).fill(0).map(() => []); + for (const [a, b] of richer) { + g[b].push(a); + } + const ans: number[] = new Array(n).fill(-1); + const dfs = (i: number) => { + if (ans[i] != -1) { + return ans; + } + ans[i] = i; + for (const j of g[i]) { + dfs(j); + if (quiet[ans[j]] < quiet[ans[i]]) { + ans[i] = ans[j]; + } + } + }; + for (let i = 0; i < n; ++i) { + dfs(i); + } + return ans; +} diff --git a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README.md b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README.md index 980f7ba73dd23..9c74ca4e6ff68 100644 --- a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README.md +++ b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README.md @@ -60,6 +60,51 @@ +**方法一:记忆化搜索** + +我们设计一个函数 $dfs(i, j)$,表示将多边形的顶点 $i$ 到 $j$ 进行三角剖分后的最低分数。那么答案就是 $dfs(0, n - 1)$。 + +函数 $dfs(i, j)$ 的计算过程如下: + +如果 $i + 1 = j$,说明多边形只有两个顶点,无法进行三角剖分,返回 $0$; + +否则,我们枚举 $i$ 和 $j$ 之间的一个顶点 $k$,即 $i \lt k \lt j$,将多边形的顶点 $i$ 到 $j$ 进行三角剖分,可以分为两个子问题:将多边形的顶点 $i$ 到 $k$ 进行三角剖分,以及将多边形的顶点 $k$ 到 $j$ 进行三角剖分。这两个子问题的最低分数分别为 $dfs(i, k)$ 和 $dfs(k, j)$,而顶点 $i$, $j$ 和 $k$ 构成的三角形的分数为 $values[i] \times values[k] \times values[j]$。那么,此次三角剖分的最低分数为 $dfs(i, k) + dfs(k, j) + values[i] \times values[k] \times values[j]$,我们取所有可能的最小值,即为 $dfs(i, j)$ 的值。 + +为了避免重复计算,我们可以使用记忆化搜索,即使用哈希表或者数组来存储已经计算过的函数值。 + +最后,我们返回 $dfs(0, n - 1)$ 即可。 + +时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为多边形的顶点数。 + +**方法二:动态规划** + +我们可以将方法一中的记忆化搜索改为动态规划。 + +定义 $f[i][j]$ 表示将多边形的顶点 $i$ 到 $j$ 进行三角剖分后的最低分数。初始时 $f[i][j]=0$,答案为 $f[0][n-1]$。 + +对于 $f[i][j]$(这里要求 $i + 1 \lt j$),我们先将 $f[i][j]$ 初始化为 $\infty$。 + +我们枚举 $i$ 和 $j$ 之间的一个顶点 $k$,即 $i \lt k \lt j$,将多边形的顶点 $i$ 到 $j$ 进行三角剖分,可以分为两个子问题:将多边形的顶点 $i$ 到 $k$ 进行三角剖分,以及将多边形的顶点 $k$ 到 $j$ 进行三角剖分。这两个子问题的最低分数分别为 $f[i][k]$ 和 $f[k][j]$,而顶点 $i$, $j$ 和 $k$ 构成的三角形的分数为 $values[i] \times values[k] \times values[j]$。那么,此次三角剖分的最低分数为 $f[i][k] + f[k][j] + values[i] \times values[k] \times values[j]$,我们取所有可能的最小值,即为 $f[i][j]$ 的值。 + +综上,我们可以得到状态转移方程: + +$$ +f[i][j]= +\begin{cases} +0, & i+1=j \\ +\min_{i ### **Python3** @@ -67,7 +112,38 @@ ```python +class Solution: + def minScoreTriangulation(self, values: List[int]) -> int: + @cache + def dfs(i: int, j: int) -> int: + if i + 1 == j: + return 0 + return min(dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j] for k in range(i + 1, j)) + + return dfs(0, len(values) - 1) +``` +```python +class Solution: + def minScoreTriangulation(self, values: List[int]) -> int: + n = len(values) + f = [[0] * n for _ in range(n)] + for i in range(n - 3, -1, -1): + for j in range(i + 2, n): + f[i][j] = min(f[i][k] + f[k][j] + values[i] * values[k] * values[j] for k in range(i + 1, j)) + return f[0][-1] +``` + +```python +class Solution: + def minScoreTriangulation(self, values: List[int]) -> int: + n = len(values) + f = [[0] * n for _ in range(n)] + for l in range(3, n + 1): + for i in range(n - l + 1): + j = i + l - 1 + f[i][j] = min(f[i][k] + f[k][j] + values[i] * values[k] * values[j] for k in range(i + 1, j)) + return f[0][-1] ``` ### **Java** @@ -75,7 +151,215 @@ ```java +class Solution { + private int n; + private int[] values; + private Integer[][] f; + + public int minScoreTriangulation(int[] values) { + n = values.length; + this.values = values; + f = new Integer[n][n]; + return dfs(0, n - 1); + } + + private int dfs(int i, int j) { + if (i + 1 == j) { + return 0; + } + if (f[i][j] != null) { + return f[i][j]; + } + int ans = 1 << 30; + for (int k = i + 1; k < j; ++k) { + ans = Math.min(ans, dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j]); + } + return f[i][j] = ans; + } +} +``` + +```java +class Solution { + public int minScoreTriangulation(int[] values) { + int n = values.length; + int[][] f = new int[n][n]; + for (int i = n - 3; i >= 0; --i) { + for (int j = i + 2; j < n; ++j) { + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = Math.min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +} +``` + +```java +class Solution { + public int minScoreTriangulation(int[] values) { + int n = values.length; + int[][] f = new int[n][n]; + for (int l = 3; l <= n; ++l) { + for (int i = 0; i + l - 1 < n; ++i) { + int j = i + l - 1; + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = Math.min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + int minScoreTriangulation(vector& values) { + int n = values.size(); + int f[n][n]; + memset(f, 0, sizeof(f)); + function dfs = [&](int i, int j) -> int { + if (i + 1 == j) { + return 0; + } + if (f[i][j]) { + return f[i][j]; + } + int ans = 1 << 30; + for (int k = i + 1; k < j; ++k) { + ans = min(ans, dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j]); + } + return f[i][j] = ans; + }; + return dfs(0, n - 1); + } +}; +``` + +```cpp +class Solution { +public: + int minScoreTriangulation(vector& values) { + int n = values.size(); + int f[n][n]; + memset(f, 0, sizeof(f)); + for (int i = n - 3; i >= 0; --i) { + for (int j = i + 2; j < n; ++j) { + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +}; +``` + +```cpp +class Solution { +public: + int minScoreTriangulation(vector& values) { + int n = values.size(); + int f[n][n]; + memset(f, 0, sizeof(f)); + for (int l = 3; l <= n; ++l) { + for (int i = 0; i + l - 1 < n; ++i) { + int j = i + l - 1; + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +}; +``` + +### **Go** + +```go +func minScoreTriangulation(values []int) int { + n := len(values) + f := [50][50]int{} + var dfs func(int, int) int + dfs = func(i, j int) int { + if i+1 == j { + return 0 + } + if f[i][j] != 0 { + return f[i][j] + } + f[i][j] = 1 << 30 + for k := i + 1; k < j; k++ { + f[i][j] = min(f[i][j], dfs(i, k)+dfs(k, j)+values[i]*values[k]*values[j]) + } + return f[i][j] + } + return dfs(0, n-1) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +```go +func minScoreTriangulation(values []int) int { + n := len(values) + f := [50][50]int{} + for i := n - 3; i >= 0; i-- { + for j := i + 2; j < n; j++ { + f[i][j] = 1 << 30 + for k := i + 1; k < j; k++ { + f[i][j] = min(f[i][j], f[i][k]+f[k][j]+values[i]*values[k]*values[j]) + } + } + } + return f[0][n-1] +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` +```go +func minScoreTriangulation(values []int) int { + n := len(values) + f := [50][50]int{} + for l := 3; l <= n; l++ { + for i := 0; i+l-1 < n; i++ { + j := i + l - 1 + f[i][j] = 1 << 30 + for k := i + 1; k < j; k++ { + f[i][j] = min(f[i][j], f[i][k]+f[k][j]+values[i]*values[k]*values[j]) + } + } + } + return f[0][n-1] +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} ``` ### **...** diff --git a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README_EN.md b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README_EN.md index 750e4b2b6444a..64696c2cba53c 100644 --- a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README_EN.md +++ b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/README_EN.md @@ -52,13 +52,252 @@ The minimum score is 144. ### **Python3** ```python +class Solution: + def minScoreTriangulation(self, values: List[int]) -> int: + @cache + def dfs(i: int, j: int) -> int: + if i + 1 == j: + return 0 + return min(dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j] for k in range(i + 1, j)) + return dfs(0, len(values) - 1) +``` + +```python +class Solution: + def minScoreTriangulation(self, values: List[int]) -> int: + n = len(values) + f = [[0] * n for _ in range(n)] + for i in range(n - 3, -1, -1): + for j in range(i + 2, n): + f[i][j] = min(f[i][k] + f[k][j] + values[i] * values[k] * values[j] for k in range(i + 1, j)) + return f[0][-1] +``` + +```python +class Solution: + def minScoreTriangulation(self, values: List[int]) -> int: + n = len(values) + f = [[0] * n for _ in range(n)] + for l in range(3, n + 1): + for i in range(n - l + 1): + j = i + l - 1 + f[i][j] = min(f[i][k] + f[k][j] + values[i] * values[k] * values[j] for k in range(i + 1, j)) + return f[0][-1] ``` ### **Java** ```java +class Solution { + private int n; + private int[] values; + private Integer[][] f; + + public int minScoreTriangulation(int[] values) { + n = values.length; + this.values = values; + f = new Integer[n][n]; + return dfs(0, n - 1); + } + + private int dfs(int i, int j) { + if (i + 1 == j) { + return 0; + } + if (f[i][j] != null) { + return f[i][j]; + } + int ans = 1 << 30; + for (int k = i + 1; k < j; ++k) { + ans = Math.min(ans, dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j]); + } + return f[i][j] = ans; + } +} +``` + +```java +class Solution { + public int minScoreTriangulation(int[] values) { + int n = values.length; + int[][] f = new int[n][n]; + for (int i = n - 3; i >= 0; --i) { + for (int j = i + 2; j < n; ++j) { + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = Math.min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +} +``` + +```java +class Solution { + public int minScoreTriangulation(int[] values) { + int n = values.length; + int[][] f = new int[n][n]; + for (int l = 3; l <= n; ++l) { + for (int i = 0; i + l - 1 < n; ++i) { + int j = i + l - 1; + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = Math.min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + int minScoreTriangulation(vector& values) { + int n = values.size(); + int f[n][n]; + memset(f, 0, sizeof(f)); + function dfs = [&](int i, int j) -> int { + if (i + 1 == j) { + return 0; + } + if (f[i][j]) { + return f[i][j]; + } + int ans = 1 << 30; + for (int k = i + 1; k < j; ++k) { + ans = min(ans, dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j]); + } + return f[i][j] = ans; + }; + return dfs(0, n - 1); + } +}; +``` + +```cpp +class Solution { +public: + int minScoreTriangulation(vector& values) { + int n = values.size(); + int f[n][n]; + memset(f, 0, sizeof(f)); + for (int i = n - 3; i >= 0; --i) { + for (int j = i + 2; j < n; ++j) { + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +}; +``` + +```cpp +class Solution { +public: + int minScoreTriangulation(vector& values) { + int n = values.size(); + int f[n][n]; + memset(f, 0, sizeof(f)); + for (int l = 3; l <= n; ++l) { + for (int i = 0; i + l - 1 < n; ++i) { + int j = i + l - 1; + f[i][j] = 1 << 30; + for (int k = i + 1; k < j; ++k) { + f[i][j] = min(f[i][j], f[i][k] + f[k][j] + values[i] * values[k] * values[j]); + } + } + } + return f[0][n - 1]; + } +}; +``` + +### **Go** + +```go +func minScoreTriangulation(values []int) int { + n := len(values) + f := [50][50]int{} + var dfs func(int, int) int + dfs = func(i, j int) int { + if i+1 == j { + return 0 + } + if f[i][j] != 0 { + return f[i][j] + } + f[i][j] = 1 << 30 + for k := i + 1; k < j; k++ { + f[i][j] = min(f[i][j], dfs(i, k)+dfs(k, j)+values[i]*values[k]*values[j]) + } + return f[i][j] + } + return dfs(0, n-1) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +```go +func minScoreTriangulation(values []int) int { + n := len(values) + f := [50][50]int{} + for i := n - 3; i >= 0; i-- { + for j := i + 2; j < n; j++ { + f[i][j] = 1 << 30 + for k := i + 1; k < j; k++ { + f[i][j] = min(f[i][j], f[i][k]+f[k][j]+values[i]*values[k]*values[j]) + } + } + } + return f[0][n-1] +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +```go +func minScoreTriangulation(values []int) int { + n := len(values) + f := [50][50]int{} + for l := 3; l <= n; l++ { + for i := 0; i+l-1 < n; i++ { + j := i + l - 1 + f[i][j] = 1 << 30 + for k := i + 1; k < j; k++ { + f[i][j] = min(f[i][j], f[i][k]+f[k][j]+values[i]*values[k]*values[j]) + } + } + } + return f[0][n-1] +} +func min(a, b int) int { + if a < b { + return a + } + return b +} ``` ### **...** diff --git a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.cpp b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.cpp new file mode 100644 index 0000000000000..b93d2f2c5d610 --- /dev/null +++ b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.cpp @@ -0,0 +1,22 @@ +class Solution { +public: + int minScoreTriangulation(vector& values) { + int n = values.size(); + int f[n][n]; + memset(f, 0, sizeof(f)); + function dfs = [&](int i, int j) -> int { + if (i + 1 == j) { + return 0; + } + if (f[i][j]) { + return f[i][j]; + } + int ans = 1 << 30; + for (int k = i + 1; k < j; ++k) { + ans = min(ans, dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j]); + } + return f[i][j] = ans; + }; + return dfs(0, n - 1); + } +}; \ No newline at end of file diff --git a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.go b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.go new file mode 100644 index 0000000000000..34e809ad0eb08 --- /dev/null +++ b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.go @@ -0,0 +1,26 @@ +func minScoreTriangulation(values []int) int { + n := len(values) + f := [50][50]int{} + var dfs func(int, int) int + dfs = func(i, j int) int { + if i+1 == j { + return 0 + } + if f[i][j] != 0 { + return f[i][j] + } + f[i][j] = 1 << 30 + for k := i + 1; k < j; k++ { + f[i][j] = min(f[i][j], dfs(i, k)+dfs(k, j)+values[i]*values[k]*values[j]) + } + return f[i][j] + } + return dfs(0, n-1) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} \ No newline at end of file diff --git a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.java b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.java new file mode 100644 index 0000000000000..544f769b24bb6 --- /dev/null +++ b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.java @@ -0,0 +1,26 @@ +class Solution { + private int n; + private int[] values; + private Integer[][] f; + + public int minScoreTriangulation(int[] values) { + n = values.length; + this.values = values; + f = new Integer[n][n]; + return dfs(0, n - 1); + } + + private int dfs(int i, int j) { + if (i + 1 == j) { + return 0; + } + if (f[i][j] != null) { + return f[i][j]; + } + int ans = 1 << 30; + for (int k = i + 1; k < j; ++k) { + ans = Math.min(ans, dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j]); + } + return f[i][j] = ans; + } +} \ No newline at end of file diff --git a/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.py b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.py new file mode 100644 index 0000000000000..b8c049ecbe6b0 --- /dev/null +++ b/solution/1000-1099/1039.Minimum Score Triangulation of Polygon/Solution.py @@ -0,0 +1,9 @@ +class Solution: + def minScoreTriangulation(self, values: List[int]) -> int: + @cache + def dfs(i: int, j: int) -> int: + if i + 1 == j: + return 0 + return min(dfs(i, k) + dfs(k, j) + values[i] * values[k] * values[j] for k in range(i + 1, j)) + + return dfs(0, len(values) - 1) diff --git a/solution/1000-1099/1053.Previous Permutation With One Swap/README.md b/solution/1000-1099/1053.Previous Permutation With One Swap/README.md index 5035a93ff78d2..e8e9e53c1596a 100644 --- a/solution/1000-1099/1053.Previous Permutation With One Swap/README.md +++ b/solution/1000-1099/1053.Previous Permutation With One Swap/README.md @@ -51,9 +51,9 @@ **方法一:贪心** -我们先从右到左遍历数组,找到第一个满足 `arr[i - 1] > arr[i]` 的下标 `i`,此时 `arr[i - 1]` 就是我们要交换的数字,我们再从右到左遍历数组,找到第一个满足 `arr[j] < arr[i - 1]` 且 `arr[j] != arr[j - 1]` 的下标 `j`,此时我们交换 `arr[i - 1]` 和 `arr[j]` 后返回即可。 +我们先从右到左遍历数组,找到第一个满足 $arr[i - 1] \gt arr[i]$ 的下标 $i$,此时 $arr[i - 1]$ 就是我们要交换的数字,我们再从右到左遍历数组,找到第一个满足 $arr[j] \lt arr[i - 1]$ 且 $arr[j] \neq arr[j - 1]$ 的下标 $j$,此时我们交换 $arr[i - 1]$ 和 $arr[j]$ 后返回即可。 -如果遍历完数组都没有找到满足条件的下标 `i`,说明数组已经是最小排列,直接返回原数组即可。 +如果遍历完数组都没有找到满足条件的下标 $i$,说明数组已经是最小排列,直接返回原数组即可。 时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组长度。 diff --git a/solution/1000-1099/1054.Distant Barcodes/README.md b/solution/1000-1099/1054.Distant Barcodes/README.md index 4c06952f12436..cbad32ced9c28 100644 --- a/solution/1000-1099/1054.Distant Barcodes/README.md +++ b/solution/1000-1099/1054.Distant Barcodes/README.md @@ -44,7 +44,7 @@ 重排条形码时,我们每次从堆顶弹出一个元素 `(v, k)`,将 `k` 添加到结果数组中,并将 `(v-1, k)` 放入队列 `q` 中。当队列长度大于 $1$ 时,弹出队首元素 `p`,若此时 `p.v` 大于 $0$,则将 `p` 放入堆中。循环,直至堆为空。 -时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$。其中 $n$ 为条形码数组的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为条形码数组的长度。 相似题目:[767. 重构字符串](/solution/0700-0799/0767.Reorganize%20String/README.md) diff --git a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README.md b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README.md index dc069b247402d..289e26b0c5d07 100644 --- a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README.md +++ b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README.md @@ -61,6 +61,16 @@ prodNums = [2,2,2,6,9,9],压缩成行程编码数组 [[2,3],[6,1],[9,2]]。 +**方法一:双指针** + +我们用两个指针 $i$ 和 $j$ 分别指向两个数组的当前位置,然后开始模拟乘法的过程。 + +对于当前位置 $i$ 和 $j$,我们取 $f=min(encoded1[i][1],encoded2[j][1])$,表示当前位置的乘积的频次,然后将 $v=encoded1[i][0] \times encoded2[j][0]$,表示当前位置的乘积的值。如果当前位置的乘积的值 $v$ 和上一个位置的乘积的值相同,则将当前位置的乘积的频次加到上一个位置的乘积的频次上,否则将当前位置的乘积的值和频次加到答案数组中。然后我们将 $encoded1[i][1]$ 和 $encoded2[j][1]$ 分别减去 $f$,如果 $encoded1[i][1]$ 或 $encoded2[j][1]$ 减为 $0$,则将对应的指针向后移动一位。 + +最后返回答案数组即可。 + +时间复杂度 $O(m + n)$,其中 $m$ 和 $n$ 分别是两个数组的长度。忽略答案数组的空间消耗,空间复杂度 $O(1)$。 + ### **Python3** @@ -68,7 +78,23 @@ prodNums = [2,2,2,6,9,9],压缩成行程编码数组 [[2,3],[6,1],[9,2]]。 ```python - +class Solution: + def findRLEArray(self, encoded1: List[List[int]], encoded2: List[List[int]]) -> List[List[int]]: + ans = [] + j = 0 + for vi, fi in encoded1: + while fi: + f = min(fi, encoded2[j][1]) + v = vi * encoded2[j][0] + if ans and ans[-1][0] == v: + ans[-1][1] += f + else: + ans.append([v, f]) + fi -= f + encoded2[j][1] -= f + if encoded2[j][1] == 0: + j += 1 + return ans ``` ### **Java** @@ -76,7 +102,94 @@ prodNums = [2,2,2,6,9,9],压缩成行程编码数组 [[2,3],[6,1],[9,2]]。 ```java +class Solution { + public List> findRLEArray(int[][] encoded1, int[][] encoded2) { + List> ans = new ArrayList<>(); + int j = 0; + for (var e : encoded1) { + int vi = e[0], fi = e[1]; + while (fi > 0) { + int f = Math.min(fi, encoded2[j][1]); + int v = vi * encoded2[j][0]; + int m = ans.size(); + if (m > 0 && ans.get(m - 1).get(0) == v) { + ans.get(m - 1).set(1, ans.get(m - 1).get(1) + f); + } else { + ans.add(new ArrayList<>(List.of(v, f))); + } + fi -= f; + encoded2[j][1] -= f; + if (encoded2[j][1] == 0) { + ++j; + } + } + } + return ans; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector> findRLEArray(vector>& encoded1, vector>& encoded2) { + vector> ans; + int j = 0; + for (auto& e : encoded1) { + int vi = e[0], fi = e[1]; + while (fi) { + int f = min(fi, encoded2[j][1]); + int v = vi * encoded2[j][0]; + if (!ans.empty() && ans.back()[0] == v) { + ans.back()[1] += f; + } else { + ans.push_back({v, f}); + } + fi -= f; + encoded2[j][1] -= f; + if (encoded2[j][1] == 0) { + ++j; + } + } + } + return ans; + } +}; +``` +### **Go** + +```go +func findRLEArray(encoded1 [][]int, encoded2 [][]int) (ans [][]int) { + j := 0 + for _, e := range encoded1 { + vi, fi := e[0], e[1] + for fi > 0 { + f := min(fi, encoded2[j][1]) + v := vi * encoded2[j][0] + if len(ans) > 0 && ans[len(ans)-1][0] == v { + ans[len(ans)-1][1] += f + } else { + ans = append(ans, []int{v, f}) + } + fi -= f + encoded2[j][1] -= f + if encoded2[j][1] == 0 { + j++ + } + } + } + return +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} ``` ### **...** diff --git a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README_EN.md b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README_EN.md index 55d0c385c2af6..bee369db2f53f 100644 --- a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README_EN.md +++ b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/README_EN.md @@ -62,13 +62,116 @@ prodNums = [2,2,2,6,9,9], which is compressed into the run-length encoded array ### **Python3** ```python - +class Solution: + def findRLEArray(self, encoded1: List[List[int]], encoded2: List[List[int]]) -> List[List[int]]: + ans = [] + j = 0 + for vi, fi in encoded1: + while fi: + f = min(fi, encoded2[j][1]) + v = vi * encoded2[j][0] + if ans and ans[-1][0] == v: + ans[-1][1] += f + else: + ans.append([v, f]) + fi -= f + encoded2[j][1] -= f + if encoded2[j][1] == 0: + j += 1 + return ans ``` ### **Java** ```java +class Solution { + public List> findRLEArray(int[][] encoded1, int[][] encoded2) { + List> ans = new ArrayList<>(); + int j = 0; + for (var e : encoded1) { + int vi = e[0], fi = e[1]; + while (fi > 0) { + int f = Math.min(fi, encoded2[j][1]); + int v = vi * encoded2[j][0]; + int m = ans.size(); + if (m > 0 && ans.get(m - 1).get(0) == v) { + ans.get(m - 1).set(1, ans.get(m - 1).get(1) + f); + } else { + ans.add(new ArrayList<>(List.of(v, f))); + } + fi -= f; + encoded2[j][1] -= f; + if (encoded2[j][1] == 0) { + ++j; + } + } + } + return ans; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector> findRLEArray(vector>& encoded1, vector>& encoded2) { + vector> ans; + int j = 0; + for (auto& e : encoded1) { + int vi = e[0], fi = e[1]; + while (fi) { + int f = min(fi, encoded2[j][1]); + int v = vi * encoded2[j][0]; + if (!ans.empty() && ans.back()[0] == v) { + ans.back()[1] += f; + } else { + ans.push_back({v, f}); + } + fi -= f; + encoded2[j][1] -= f; + if (encoded2[j][1] == 0) { + ++j; + } + } + } + return ans; + } +}; +``` +### **Go** + +```go +func findRLEArray(encoded1 [][]int, encoded2 [][]int) (ans [][]int) { + j := 0 + for _, e := range encoded1 { + vi, fi := e[0], e[1] + for fi > 0 { + f := min(fi, encoded2[j][1]) + v := vi * encoded2[j][0] + if len(ans) > 0 && ans[len(ans)-1][0] == v { + ans[len(ans)-1][1] += f + } else { + ans = append(ans, []int{v, f}) + } + fi -= f + encoded2[j][1] -= f + if encoded2[j][1] == 0 { + j++ + } + } + } + return +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} ``` ### **...** diff --git a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.cpp b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.cpp new file mode 100644 index 0000000000000..b2c5e89738bb8 --- /dev/null +++ b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.cpp @@ -0,0 +1,25 @@ +class Solution { +public: + vector> findRLEArray(vector>& encoded1, vector>& encoded2) { + vector> ans; + int j = 0; + for (auto& e : encoded1) { + int vi = e[0], fi = e[1]; + while (fi) { + int f = min(fi, encoded2[j][1]); + int v = vi * encoded2[j][0]; + if (!ans.empty() && ans.back()[0] == v) { + ans.back()[1] += f; + } else { + ans.push_back({v, f}); + } + fi -= f; + encoded2[j][1] -= f; + if (encoded2[j][1] == 0) { + ++j; + } + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.go b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.go new file mode 100644 index 0000000000000..f711f56a2d34c --- /dev/null +++ b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.go @@ -0,0 +1,28 @@ +func findRLEArray(encoded1 [][]int, encoded2 [][]int) (ans [][]int) { + j := 0 + for _, e := range encoded1 { + vi, fi := e[0], e[1] + for fi > 0 { + f := min(fi, encoded2[j][1]) + v := vi * encoded2[j][0] + if len(ans) > 0 && ans[len(ans)-1][0] == v { + ans[len(ans)-1][1] += f + } else { + ans = append(ans, []int{v, f}) + } + fi -= f + encoded2[j][1] -= f + if encoded2[j][1] == 0 { + j++ + } + } + } + return +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} \ No newline at end of file diff --git a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.java b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.java new file mode 100644 index 0000000000000..77c0dbbdddb57 --- /dev/null +++ b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.java @@ -0,0 +1,25 @@ +class Solution { + public List> findRLEArray(int[][] encoded1, int[][] encoded2) { + List> ans = new ArrayList<>(); + int j = 0; + for (var e : encoded1) { + int vi = e[0], fi = e[1]; + while (fi > 0) { + int f = Math.min(fi, encoded2[j][1]); + int v = vi * encoded2[j][0]; + int m = ans.size(); + if (m > 0 && ans.get(m - 1).get(0) == v) { + ans.get(m - 1).set(1, ans.get(m - 1).get(1) + f); + } else { + ans.add(new ArrayList<>(List.of(v, f))); + } + fi -= f; + encoded2[j][1] -= f; + if (encoded2[j][1] == 0) { + ++j; + } + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.py b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.py new file mode 100644 index 0000000000000..0c9ff5e66d2a6 --- /dev/null +++ b/solution/1800-1899/1868.Product of Two Run-Length Encoded Arrays/Solution.py @@ -0,0 +1,17 @@ +class Solution: + def findRLEArray(self, encoded1: List[List[int]], encoded2: List[List[int]]) -> List[List[int]]: + ans = [] + j = 0 + for vi, fi in encoded1: + while fi: + f = min(fi, encoded2[j][1]) + v = vi * encoded2[j][0] + if ans and ans[-1][0] == v: + ans[-1][1] += f + else: + ans.append([v, f]) + fi -= f + encoded2[j][1] -= f + if encoded2[j][1] == 0: + j += 1 + return ans