diff --git a/solution/0300-0399/0377.Combination Sum IV/README.md b/solution/0300-0399/0377.Combination Sum IV/README.md index d011d3b94db3f..bea223d8e387d 100644 --- a/solution/0300-0399/0377.Combination Sum IV/README.md +++ b/solution/0300-0399/0377.Combination Sum IV/README.md @@ -131,7 +131,7 @@ func combinationSum4(nums []int, target int) int { ```ts function combinationSum4(nums: number[], target: number): number { - const f: number[] = new Array(target + 1).fill(0); + const f: number[] = Array(target + 1).fill(0); f[0] = 1; for (let i = 1; i <= target; ++i) { for (const x of nums) { @@ -151,7 +151,7 @@ function combinationSum4(nums: number[], target: number): number { * @return {number} */ var combinationSum4 = function (nums, target) { - const f = new Array(target + 1).fill(0); + const f = Array(target + 1).fill(0); f[0] = 1; for (let i = 1; i <= target; ++i) { for (const x of nums) { diff --git a/solution/0300-0399/0377.Combination Sum IV/README_EN.md b/solution/0300-0399/0377.Combination Sum IV/README_EN.md index 5512cef711881..3f82427de23ac 100644 --- a/solution/0300-0399/0377.Combination Sum IV/README_EN.md +++ b/solution/0300-0399/0377.Combination Sum IV/README_EN.md @@ -50,7 +50,15 @@ Note that different sequences are counted as different combinations. ## Solutions -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i]$ as the number of combinations that sum up to $i$. Initially, $f[0] = 1$, and the rest $f[i] = 0$. The final answer is $f[target]$. + +For $f[i]$, we can enumerate each element $x$ in the array. If $i \ge x$, then $f[i] = f[i] + f[i - x]$. + +Finally, return $f[target]$. + +The time complexity is $O(n \times target)$, and the space complexity is $O(target)$, where $n$ is the length of the array. @@ -118,7 +126,7 @@ func combinationSum4(nums []int, target int) int { ```ts function combinationSum4(nums: number[], target: number): number { - const f: number[] = new Array(target + 1).fill(0); + const f: number[] = Array(target + 1).fill(0); f[0] = 1; for (let i = 1; i <= target; ++i) { for (const x of nums) { @@ -138,7 +146,7 @@ function combinationSum4(nums: number[], target: number): number { * @return {number} */ var combinationSum4 = function (nums, target) { - const f = new Array(target + 1).fill(0); + const f = Array(target + 1).fill(0); f[0] = 1; for (let i = 1; i <= target; ++i) { for (const x of nums) { diff --git a/solution/0300-0399/0377.Combination Sum IV/Solution.js b/solution/0300-0399/0377.Combination Sum IV/Solution.js index 4c81a62884c92..c3d1dcba1653c 100644 --- a/solution/0300-0399/0377.Combination Sum IV/Solution.js +++ b/solution/0300-0399/0377.Combination Sum IV/Solution.js @@ -4,7 +4,7 @@ * @return {number} */ var combinationSum4 = function (nums, target) { - const f = new Array(target + 1).fill(0); + const f = Array(target + 1).fill(0); f[0] = 1; for (let i = 1; i <= target; ++i) { for (const x of nums) { diff --git a/solution/0300-0399/0377.Combination Sum IV/Solution.ts b/solution/0300-0399/0377.Combination Sum IV/Solution.ts index 297f6487e7020..7e3965b9b9c56 100644 --- a/solution/0300-0399/0377.Combination Sum IV/Solution.ts +++ b/solution/0300-0399/0377.Combination Sum IV/Solution.ts @@ -1,5 +1,5 @@ function combinationSum4(nums: number[], target: number): number { - const f: number[] = new Array(target + 1).fill(0); + const f: number[] = Array(target + 1).fill(0); f[0] = 1; for (let i = 1; i <= target; ++i) { for (const x of nums) { diff --git a/solution/3100-3199/3120.Count the Number of Special Characters I/README.md b/solution/3100-3199/3120.Count the Number of Special Characters I/README.md index ed5ba637ef054..4d032fffaf589 100644 --- a/solution/3100-3199/3120.Count the Number of Special Characters I/README.md +++ b/solution/3100-3199/3120.Count the Number of Special Characters I/README.md @@ -61,24 +61,87 @@ ## 解法 -### 方法一 +### 方法一:哈希表或数组 + +我们用一个哈希表或数组 $s$ 来记录字符串 $word$ 中出现的字符。然后遍历 $26$ 个字母,如果小写字母和大写字母都在 $s$ 中出现,则特殊字符的数量加一。 + +最后返回特殊字符的数量即可。 + +时间复杂度 $O(n + |\Sigma|)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 为字符串 $word$ 的长度;而 $|\Sigma|$ 为字符集大小,本题中 $|\Sigma| \leq 128$。 ```python - +class Solution: + def numberOfSpecialChars(self, word: str) -> int: + s = set(word) + return sum(a in s and b in s for a, b in zip(ascii_lowercase, ascii_uppercase)) ``` ```java - +class Solution { + public int numberOfSpecialChars(String word) { + boolean[] s = new boolean['z' + 1]; + for (int i = 0; i < word.length(); ++i) { + s[word.charAt(i)] = true; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (s['a' + i] && s['A' + i]) { + ++ans; + } + } + return ans; + } +} ``` ```cpp - +class Solution { +public: + int numberOfSpecialChars(string word) { + vector s('z' + 1); + for (char& c : word) { + s[c] = true; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + ans += s['a' + i] && s['A' + i]; + } + return ans; + } +}; ``` ```go +func numberOfSpecialChars(word string) (ans int) { + s := make([]bool, 'z'+1) + for _, c := range word { + s[c] = true + } + for i := 0; i < 26; i++ { + if s['a'+i] && s['A'+i] { + ans++ + } + } + return +} +``` +```ts +function numberOfSpecialChars(word: string): number { + const s: boolean[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => false); + for (let i = 0; i < word.length; ++i) { + s[word.charCodeAt(i)] = true; + } + let ans: number = 0; + for (let i = 0; i < 26; ++i) { + if (s['a'.charCodeAt(0) + i] && s['A'.charCodeAt(0) + i]) { + ++ans; + } + } + return ans; +} ``` diff --git a/solution/3100-3199/3120.Count the Number of Special Characters I/README_EN.md b/solution/3100-3199/3120.Count the Number of Special Characters I/README_EN.md index 59ac560816b13..fd27ce027d7f7 100644 --- a/solution/3100-3199/3120.Count the Number of Special Characters I/README_EN.md +++ b/solution/3100-3199/3120.Count the Number of Special Characters I/README_EN.md @@ -57,24 +57,87 @@ ## Solutions -### Solution 1 +### Solution 1: Hash Table or Array + +We use a hash table or array $s$ to record the characters that appear in the string $word$. Then we traverse the 26 letters. If both the lowercase and uppercase letters appear in $s$, the count of special characters is incremented by one. + +Finally, return the count of special characters. + +The time complexity is $O(n + |\Sigma|)$, and the space complexity is $O(|\Sigma|)$. Where $n$ is the length of the string $word$, and $|\Sigma|$ is the size of the character set. In this problem, $|\Sigma| \leq 128$. ```python - +class Solution: + def numberOfSpecialChars(self, word: str) -> int: + s = set(word) + return sum(a in s and b in s for a, b in zip(ascii_lowercase, ascii_uppercase)) ``` ```java - +class Solution { + public int numberOfSpecialChars(String word) { + boolean[] s = new boolean['z' + 1]; + for (int i = 0; i < word.length(); ++i) { + s[word.charAt(i)] = true; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (s['a' + i] && s['A' + i]) { + ++ans; + } + } + return ans; + } +} ``` ```cpp - +class Solution { +public: + int numberOfSpecialChars(string word) { + vector s('z' + 1); + for (char& c : word) { + s[c] = true; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + ans += s['a' + i] && s['A' + i]; + } + return ans; + } +}; ``` ```go +func numberOfSpecialChars(word string) (ans int) { + s := make([]bool, 'z'+1) + for _, c := range word { + s[c] = true + } + for i := 0; i < 26; i++ { + if s['a'+i] && s['A'+i] { + ans++ + } + } + return +} +``` +```ts +function numberOfSpecialChars(word: string): number { + const s: boolean[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => false); + for (let i = 0; i < word.length; ++i) { + s[word.charCodeAt(i)] = true; + } + let ans: number = 0; + for (let i = 0; i < 26; ++i) { + if (s['a'.charCodeAt(0) + i] && s['A'.charCodeAt(0) + i]) { + ++ans; + } + } + return ans; +} ``` diff --git a/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.cpp b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.cpp new file mode 100644 index 0000000000000..e1a9a583516d5 --- /dev/null +++ b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + int numberOfSpecialChars(string word) { + vector s('z' + 1); + for (char& c : word) { + s[c] = true; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + ans += s['a' + i] && s['A' + i]; + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.go b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.go new file mode 100644 index 0000000000000..448000c943978 --- /dev/null +++ b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.go @@ -0,0 +1,12 @@ +func numberOfSpecialChars(word string) (ans int) { + s := make([]bool, 'z'+1) + for _, c := range word { + s[c] = true + } + for i := 0; i < 26; i++ { + if s['a'+i] && s['A'+i] { + ans++ + } + } + return +} \ No newline at end of file diff --git a/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.java b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.java new file mode 100644 index 0000000000000..4a6a771f1784b --- /dev/null +++ b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.java @@ -0,0 +1,15 @@ +class Solution { + public int numberOfSpecialChars(String word) { + boolean[] s = new boolean['z' + 1]; + for (int i = 0; i < word.length(); ++i) { + s[word.charAt(i)] = true; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (s['a' + i] && s['A' + i]) { + ++ans; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.py b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.py new file mode 100644 index 0000000000000..1c5dbe65d1844 --- /dev/null +++ b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.py @@ -0,0 +1,4 @@ +class Solution: + def numberOfSpecialChars(self, word: str) -> int: + s = set(word) + return sum(a in s and b in s for a, b in zip(ascii_lowercase, ascii_uppercase)) diff --git a/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.ts b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.ts new file mode 100644 index 0000000000000..ea856c2295dfe --- /dev/null +++ b/solution/3100-3199/3120.Count the Number of Special Characters I/Solution.ts @@ -0,0 +1,13 @@ +function numberOfSpecialChars(word: string): number { + const s: boolean[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => false); + for (let i = 0; i < word.length; ++i) { + s[word.charCodeAt(i)] = true; + } + let ans: number = 0; + for (let i = 0; i < 26; ++i) { + if (s['a'.charCodeAt(0) + i] && s['A'.charCodeAt(0) + i]) { + ++ans; + } + } + return ans; +} diff --git a/solution/3100-3199/3121.Count the Number of Special Characters II/README.md b/solution/3100-3199/3121.Count the Number of Special Characters II/README.md index d41bf3317f4c9..40f6392166526 100644 --- a/solution/3100-3199/3121.Count the Number of Special Characters II/README.md +++ b/solution/3100-3199/3121.Count the Number of Special Characters II/README.md @@ -61,24 +61,121 @@ ## 解法 -### 方法一 +### 方法一:哈希表或数组 + +我们定义两个哈希表或数组 $\textit{first}$ 和 $\textit{last}$,用于存储每个字母第一次出现的位置和最后一次出现的位置。 + +然后我们遍历字符串 $\textit{word}$,更新 $\textit{first}$ 和 $\textit{last}$。 + +最后我们遍历所有的小写字母和大写字母,如果 $\textit{last}[a]$ 存在且 $\textit{first}[b]$ 存在且 $\textit{last}[a] < \textit{first}[b]$,则说明字母 $a$ 是一个特殊字母,将答案加一。 + +时间复杂度 $O(n + |\Sigma|)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 为字符串 $\textit{word}$ 的长度;而 $|\Sigma|$ 为字符集大小,本题中 $|\Sigma| \leq 128$。 ```python - +class Solution: + def numberOfSpecialChars(self, word: str) -> int: + first, last = {}, {} + for i, c in enumerate(word): + if c not in first: + first[c] = i + last[c] = i + return sum( + a in last and b in first and last[a] < first[b] + for a, b in zip(ascii_lowercase, ascii_uppercase) + ) ``` ```java - +class Solution { + public int numberOfSpecialChars(String word) { + int[] first = new int['z' + 1]; + int[] last = new int['z' + 1]; + for (int i = 1; i <= word.length(); ++i) { + int j = word.charAt(i - 1); + if (first[j] == 0) { + first[j] = i; + } + last[j] = i; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (last['a' + i] > 0 && first['A' + i] > 0 && last['a' + i] < first['A' + i]) { + ++ans; + } + } + return ans; + } +} ``` ```cpp - +class Solution { +public: + int numberOfSpecialChars(string word) { + vector first('z' + 1); + vector last('z' + 1); + for (int i = 1; i <= word.size(); ++i) { + int j = word[i - 1]; + if (first[j] == 0) { + first[j] = i; + } + last[j] = i; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (last['a' + i] && first['A' + i] && last['a' + i] < first['A' + i]) { + ++ans; + } + } + return ans; + } +}; ``` ```go +func numberOfSpecialChars(word string) (ans int) { + first := make([]int, 'z'+1) + last := make([]int, 'z'+1) + for i, c := range word { + if first[c] == 0 { + first[c] = i + 1 + } + last[c] = i + 1 + } + for i := 0; i < 26; i++ { + if last['a'+i] > 0 && first['A'+i] > 0 && last['a'+i] < first['A'+i] { + ans++ + } + } + return +} +``` +```ts +function numberOfSpecialChars(word: string): number { + const first: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0); + const last: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0); + for (let i = 0; i < word.length; ++i) { + const j = word.charCodeAt(i); + if (first[j] === 0) { + first[j] = i + 1; + } + last[j] = i + 1; + } + let ans: number = 0; + for (let i = 0; i < 26; ++i) { + if ( + last['a'.charCodeAt(0) + i] && + first['A'.charCodeAt(0) + i] && + last['a'.charCodeAt(0) + i] < first['A'.charCodeAt(0) + i] + ) { + ++ans; + } + } + return ans; +} ``` diff --git a/solution/3100-3199/3121.Count the Number of Special Characters II/README_EN.md b/solution/3100-3199/3121.Count the Number of Special Characters II/README_EN.md index 60c4a9a847153..b96724d3ea94b 100644 --- a/solution/3100-3199/3121.Count the Number of Special Characters II/README_EN.md +++ b/solution/3100-3199/3121.Count the Number of Special Characters II/README_EN.md @@ -57,24 +57,121 @@ ## Solutions -### Solution 1 +### Solution 1: Hash Table or Array + +We define two hash tables or arrays `first` and `last` to store the positions where each letter first appears and last appears respectively. + +Then we traverse the string `word`, updating `first` and `last`. + +Finally, we traverse all lowercase and uppercase letters. If `last[a]` exists and `first[b]` exists and `last[a] < first[b]`, it means that the letter `a` is a special letter, and we increment the answer by one. + +The time complexity is $O(n + |\Sigma|)$, and the space complexity is $O(|\Sigma|)$. Where $n$ is the length of the string `word`, and $|\Sigma|$ is the size of the character set. In this problem, $|\Sigma| \leq 128$. ```python - +class Solution: + def numberOfSpecialChars(self, word: str) -> int: + first, last = {}, {} + for i, c in enumerate(word): + if c not in first: + first[c] = i + last[c] = i + return sum( + a in last and b in first and last[a] < first[b] + for a, b in zip(ascii_lowercase, ascii_uppercase) + ) ``` ```java - +class Solution { + public int numberOfSpecialChars(String word) { + int[] first = new int['z' + 1]; + int[] last = new int['z' + 1]; + for (int i = 1; i <= word.length(); ++i) { + int j = word.charAt(i - 1); + if (first[j] == 0) { + first[j] = i; + } + last[j] = i; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (last['a' + i] > 0 && first['A' + i] > 0 && last['a' + i] < first['A' + i]) { + ++ans; + } + } + return ans; + } +} ``` ```cpp - +class Solution { +public: + int numberOfSpecialChars(string word) { + vector first('z' + 1); + vector last('z' + 1); + for (int i = 1; i <= word.size(); ++i) { + int j = word[i - 1]; + if (first[j] == 0) { + first[j] = i; + } + last[j] = i; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (last['a' + i] && first['A' + i] && last['a' + i] < first['A' + i]) { + ++ans; + } + } + return ans; + } +}; ``` ```go +func numberOfSpecialChars(word string) (ans int) { + first := make([]int, 'z'+1) + last := make([]int, 'z'+1) + for i, c := range word { + if first[c] == 0 { + first[c] = i + 1 + } + last[c] = i + 1 + } + for i := 0; i < 26; i++ { + if last['a'+i] > 0 && first['A'+i] > 0 && last['a'+i] < first['A'+i] { + ans++ + } + } + return +} +``` +```ts +function numberOfSpecialChars(word: string): number { + const first: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0); + const last: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0); + for (let i = 0; i < word.length; ++i) { + const j = word.charCodeAt(i); + if (first[j] === 0) { + first[j] = i + 1; + } + last[j] = i + 1; + } + let ans: number = 0; + for (let i = 0; i < 26; ++i) { + if ( + last['a'.charCodeAt(0) + i] && + first['A'.charCodeAt(0) + i] && + last['a'.charCodeAt(0) + i] < first['A'.charCodeAt(0) + i] + ) { + ++ans; + } + } + return ans; +} ``` diff --git a/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.cpp b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.cpp new file mode 100644 index 0000000000000..b93f8ce61d075 --- /dev/null +++ b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.cpp @@ -0,0 +1,21 @@ +class Solution { +public: + int numberOfSpecialChars(string word) { + vector first('z' + 1); + vector last('z' + 1); + for (int i = 1; i <= word.size(); ++i) { + int j = word[i - 1]; + if (first[j] == 0) { + first[j] = i; + } + last[j] = i; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (last['a' + i] && first['A' + i] && last['a' + i] < first['A' + i]) { + ++ans; + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.go b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.go new file mode 100644 index 0000000000000..3604127301b1f --- /dev/null +++ b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.go @@ -0,0 +1,16 @@ +func numberOfSpecialChars(word string) (ans int) { + first := make([]int, 'z'+1) + last := make([]int, 'z'+1) + for i, c := range word { + if first[c] == 0 { + first[c] = i + 1 + } + last[c] = i + 1 + } + for i := 0; i < 26; i++ { + if last['a'+i] > 0 && first['A'+i] > 0 && last['a'+i] < first['A'+i] { + ans++ + } + } + return +} \ No newline at end of file diff --git a/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.java b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.java new file mode 100644 index 0000000000000..bb7527b8427db --- /dev/null +++ b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.java @@ -0,0 +1,20 @@ +class Solution { + public int numberOfSpecialChars(String word) { + int[] first = new int['z' + 1]; + int[] last = new int['z' + 1]; + for (int i = 1; i <= word.length(); ++i) { + int j = word.charAt(i - 1); + if (first[j] == 0) { + first[j] = i; + } + last[j] = i; + } + int ans = 0; + for (int i = 0; i < 26; ++i) { + if (last['a' + i] > 0 && first['A' + i] > 0 && last['a' + i] < first['A' + i]) { + ++ans; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.py b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.py new file mode 100644 index 0000000000000..a1ebb0e2619f4 --- /dev/null +++ b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.py @@ -0,0 +1,11 @@ +class Solution: + def numberOfSpecialChars(self, word: str) -> int: + first, last = {}, {} + for i, c in enumerate(word): + if c not in first: + first[c] = i + last[c] = i + return sum( + a in last and b in first and last[a] < first[b] + for a, b in zip(ascii_lowercase, ascii_uppercase) + ) diff --git a/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.ts b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.ts new file mode 100644 index 0000000000000..caa1f7c0be193 --- /dev/null +++ b/solution/3100-3199/3121.Count the Number of Special Characters II/Solution.ts @@ -0,0 +1,22 @@ +function numberOfSpecialChars(word: string): number { + const first: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0); + const last: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0); + for (let i = 0; i < word.length; ++i) { + const j = word.charCodeAt(i); + if (first[j] === 0) { + first[j] = i + 1; + } + last[j] = i + 1; + } + let ans: number = 0; + for (let i = 0; i < 26; ++i) { + if ( + last['a'.charCodeAt(0) + i] && + first['A'.charCodeAt(0) + i] && + last['a'.charCodeAt(0) + i] < first['A'.charCodeAt(0) + i] + ) { + ++ans; + } + } + return ans; +} diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md index dd80c7ce3a8db..6dfc3c77d0a15 100644 --- a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md @@ -78,24 +78,173 @@ ## 解法 -### 方法一 +### 方法一:动态规划 + +我们注意到,矩阵中格子的值只有 $10$ 种可能,题目需要我们求出每一列数字相同,且相邻列数字不同的最小操作次数。那么我们只需要考虑将数字修改为 $0$ 到 $9$ 的情况即可。 + +我们定义状态 $f[i][j]$ 表示前 $[0,..i]$ 列数字,且第 $i$ 列数字为 $j$ 的最小操作次数。那么我们可以得到状态转移方程: + +$$ +f[i][j] = \min_{k \neq j} f[i-1][k] + m - \text{cnt}[j] +$$ + +其中 $\text{cnt}[j]$ 表示第 $i$ 列数字为 $j$ 的个数。 + +最后我们只需要求出 $f[n-1][j]$ 的最小值即可。 + +时间复杂度 $O(n \times (m + C^2))$,空间复杂度 $O(n \times C)$。其中 $m$ 和 $n$ 分别表示矩阵的行数和列数;而 $C$ 表示数字的种类数,这里 $C = 10$。 ```python - +class Solution: + def minimumOperations(self, grid: List[List[int]]) -> int: + m, n = len(grid), len(grid[0]) + f = [[inf] * 10 for _ in range(n)] + for i in range(n): + cnt = [0] * 10 + for j in range(m): + cnt[grid[j][i]] += 1 + if i == 0: + for j in range(10): + f[i][j] = m - cnt[j] + else: + for j in range(10): + for k in range(10): + if k != j: + f[i][j] = min(f[i][j], f[i - 1][k] + m - cnt[j]) + return min(f[-1]) ``` ```java - +class Solution { + public int minimumOperations(int[][] grid) { + int m = grid.length, n = grid[0].length; + int[][] f = new int[n][10]; + final int inf = 1 << 29; + for (var g : f) { + Arrays.fill(g, inf); + } + for (int i = 0; i < n; ++i) { + int[] cnt = new int[10]; + for (int j = 0; j < m; ++j) { + ++cnt[grid[j][i]]; + } + if (i == 0) { + for (int j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (int j = 0; j < 10; ++j) { + for (int k = 0; k < 10; ++k) { + if (k != j) { + f[i][j] = Math.min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + int ans = inf; + for (int j = 0; j < 10; ++j) { + ans = Math.min(ans, f[n - 1][j]); + } + return ans; + } +} ``` ```cpp - +class Solution { +public: + int minimumOperations(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + int f[n][10]; + memset(f, 0x3f, sizeof(f)); + for (int i = 0; i < n; ++i) { + int cnt[10]{}; + for (int j = 0; j < m; ++j) { + ++cnt[grid[j][i]]; + } + if (i == 0) { + for (int j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (int j = 0; j < 10; ++j) { + for (int k = 0; k < 10; ++k) { + if (k != j) { + f[i][j] = min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + return *min_element(f[n - 1], f[n - 1] + 10); + } +}; ``` ```go +func minimumOperations(grid [][]int) int { + m, n := len(grid), len(grid[0]) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, 10) + for j := range f[i] { + f[i][j] = 1 << 29 + } + } + for i := 0; i < n; i++ { + cnt := [10]int{} + for j := 0; j < m; j++ { + cnt[grid[j][i]]++ + } + if i == 0 { + for j := 0; j < 10; j++ { + f[i][j] = m - cnt[j] + } + } else { + for j := 0; j < 10; j++ { + for k := 0; k < 10; k++ { + if j != k { + f[i][j] = min(f[i][j], f[i-1][k]+m-cnt[j]) + } + } + } + } + } + return slices.Min(f[n-1]) +} +``` +```ts +function minimumOperations(grid: number[][]): number { + const m = grid.length; + const n = grid[0].length; + const f: number[][] = Array.from({ length: n }, () => + Array.from({ length: 10 }, () => Infinity), + ); + for (let i = 0; i < n; ++i) { + const cnt: number[] = Array(10).fill(0); + for (let j = 0; j < m; ++j) { + cnt[grid[j][i]]++; + } + if (i === 0) { + for (let j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (let j = 0; j < 10; ++j) { + for (let k = 0; k < 10; ++k) { + if (j !== k) { + f[i][j] = Math.min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + return Math.min(...f[n - 1]); +} ``` diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md index 08e612b74c3e8..7e99715779d28 100644 --- a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md @@ -74,24 +74,173 @@ ## Solutions -### Solution 1 +### Solution 1: Dynamic Programming + +We notice that the values in the cells of the matrix only have 10 possibilities. The problem requires us to find the minimum number of operations for each column to have the same number, and the numbers in adjacent columns are different. Therefore, we only need to consider the case of modifying the number to 0 to 9. + +We define the state $f[i][j]$ to represent the minimum number of operations for the numbers in the first $[0,..i]$ columns, and the number in the $i$-th column is $j$. Then we can get the state transition equation: + +$$ +f[i][j] = \min_{k \neq j} (f[i-1][k] + m - \text{cnt}[j]) +$$ + +Where $\text{cnt}[j]$ represents the number of cells in the $i$-th column that are $j$. + +Finally, we only need to find the minimum value of $f[n-1][j]$. + +The time complexity is $O(n \times (m + C^2))$, and the space complexity is $O(n \times C)$. Where $m$ and $n$ represent the number of rows and columns in the matrix respectively; and $C$ represents the number of types of numbers, here $C = 10$. ```python - +class Solution: + def minimumOperations(self, grid: List[List[int]]) -> int: + m, n = len(grid), len(grid[0]) + f = [[inf] * 10 for _ in range(n)] + for i in range(n): + cnt = [0] * 10 + for j in range(m): + cnt[grid[j][i]] += 1 + if i == 0: + for j in range(10): + f[i][j] = m - cnt[j] + else: + for j in range(10): + for k in range(10): + if k != j: + f[i][j] = min(f[i][j], f[i - 1][k] + m - cnt[j]) + return min(f[-1]) ``` ```java - +class Solution { + public int minimumOperations(int[][] grid) { + int m = grid.length, n = grid[0].length; + int[][] f = new int[n][10]; + final int inf = 1 << 29; + for (var g : f) { + Arrays.fill(g, inf); + } + for (int i = 0; i < n; ++i) { + int[] cnt = new int[10]; + for (int j = 0; j < m; ++j) { + ++cnt[grid[j][i]]; + } + if (i == 0) { + for (int j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (int j = 0; j < 10; ++j) { + for (int k = 0; k < 10; ++k) { + if (k != j) { + f[i][j] = Math.min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + int ans = inf; + for (int j = 0; j < 10; ++j) { + ans = Math.min(ans, f[n - 1][j]); + } + return ans; + } +} ``` ```cpp - +class Solution { +public: + int minimumOperations(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + int f[n][10]; + memset(f, 0x3f, sizeof(f)); + for (int i = 0; i < n; ++i) { + int cnt[10]{}; + for (int j = 0; j < m; ++j) { + ++cnt[grid[j][i]]; + } + if (i == 0) { + for (int j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (int j = 0; j < 10; ++j) { + for (int k = 0; k < 10; ++k) { + if (k != j) { + f[i][j] = min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + return *min_element(f[n - 1], f[n - 1] + 10); + } +}; ``` ```go +func minimumOperations(grid [][]int) int { + m, n := len(grid), len(grid[0]) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, 10) + for j := range f[i] { + f[i][j] = 1 << 29 + } + } + for i := 0; i < n; i++ { + cnt := [10]int{} + for j := 0; j < m; j++ { + cnt[grid[j][i]]++ + } + if i == 0 { + for j := 0; j < 10; j++ { + f[i][j] = m - cnt[j] + } + } else { + for j := 0; j < 10; j++ { + for k := 0; k < 10; k++ { + if j != k { + f[i][j] = min(f[i][j], f[i-1][k]+m-cnt[j]) + } + } + } + } + } + return slices.Min(f[n-1]) +} +``` +```ts +function minimumOperations(grid: number[][]): number { + const m = grid.length; + const n = grid[0].length; + const f: number[][] = Array.from({ length: n }, () => + Array.from({ length: 10 }, () => Infinity), + ); + for (let i = 0; i < n; ++i) { + const cnt: number[] = Array(10).fill(0); + for (let j = 0; j < m; ++j) { + cnt[grid[j][i]]++; + } + if (i === 0) { + for (let j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (let j = 0; j < 10; ++j) { + for (let k = 0; k < 10; ++k) { + if (j !== k) { + f[i][j] = Math.min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + return Math.min(...f[n - 1]); +} ``` diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.cpp b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.cpp new file mode 100644 index 0000000000000..fce1249c3d378 --- /dev/null +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int minimumOperations(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + int f[n][10]; + memset(f, 0x3f, sizeof(f)); + for (int i = 0; i < n; ++i) { + int cnt[10]{}; + for (int j = 0; j < m; ++j) { + ++cnt[grid[j][i]]; + } + if (i == 0) { + for (int j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (int j = 0; j < 10; ++j) { + for (int k = 0; k < 10; ++k) { + if (k != j) { + f[i][j] = min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + return *min_element(f[n - 1], f[n - 1] + 10); + } +}; \ No newline at end of file diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.go b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.go new file mode 100644 index 0000000000000..106bfe54a4e6d --- /dev/null +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.go @@ -0,0 +1,30 @@ +func minimumOperations(grid [][]int) int { + m, n := len(grid), len(grid[0]) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, 10) + for j := range f[i] { + f[i][j] = 1 << 29 + } + } + for i := 0; i < n; i++ { + cnt := [10]int{} + for j := 0; j < m; j++ { + cnt[grid[j][i]]++ + } + if i == 0 { + for j := 0; j < 10; j++ { + f[i][j] = m - cnt[j] + } + } else { + for j := 0; j < 10; j++ { + for k := 0; k < 10; k++ { + if j != k { + f[i][j] = min(f[i][j], f[i-1][k]+m-cnt[j]) + } + } + } + } + } + return slices.Min(f[n-1]) +} \ No newline at end of file diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.java b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.java new file mode 100644 index 0000000000000..358cfd0a8d903 --- /dev/null +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.java @@ -0,0 +1,34 @@ +class Solution { + public int minimumOperations(int[][] grid) { + int m = grid.length, n = grid[0].length; + int[][] f = new int[n][10]; + final int inf = 1 << 29; + for (var g : f) { + Arrays.fill(g, inf); + } + for (int i = 0; i < n; ++i) { + int[] cnt = new int[10]; + for (int j = 0; j < m; ++j) { + ++cnt[grid[j][i]]; + } + if (i == 0) { + for (int j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (int j = 0; j < 10; ++j) { + for (int k = 0; k < 10; ++k) { + if (k != j) { + f[i][j] = Math.min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + int ans = inf; + for (int j = 0; j < 10; ++j) { + ans = Math.min(ans, f[n - 1][j]); + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.py b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.py new file mode 100644 index 0000000000000..1786aa8e698f9 --- /dev/null +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.py @@ -0,0 +1,17 @@ +class Solution: + def minimumOperations(self, grid: List[List[int]]) -> int: + m, n = len(grid), len(grid[0]) + f = [[inf] * 10 for _ in range(n)] + for i in range(n): + cnt = [0] * 10 + for j in range(m): + cnt[grid[j][i]] += 1 + if i == 0: + for j in range(10): + f[i][j] = m - cnt[j] + else: + for j in range(10): + for k in range(10): + if k != j: + f[i][j] = min(f[i][j], f[i - 1][k] + m - cnt[j]) + return min(f[-1]) diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.ts b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.ts new file mode 100644 index 0000000000000..cd7fd7aa165e4 --- /dev/null +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/Solution.ts @@ -0,0 +1,27 @@ +function minimumOperations(grid: number[][]): number { + const m = grid.length; + const n = grid[0].length; + const f: number[][] = Array.from({ length: n }, () => + Array.from({ length: 10 }, () => Infinity), + ); + for (let i = 0; i < n; ++i) { + const cnt: number[] = Array(10).fill(0); + for (let j = 0; j < m; ++j) { + cnt[grid[j][i]]++; + } + if (i === 0) { + for (let j = 0; j < 10; ++j) { + f[i][j] = m - cnt[j]; + } + } else { + for (let j = 0; j < 10; ++j) { + for (let k = 0; k < 10; ++k) { + if (j !== k) { + f[i][j] = Math.min(f[i][j], f[i - 1][k] + m - cnt[j]); + } + } + } + } + } + return Math.min(...f[n - 1]); +} diff --git a/solution/3100-3199/3123.Find Edges in Shortest Paths/README.md b/solution/3100-3199/3123.Find Edges in Shortest Paths/README.md index 1cce4a2e6098b..6f1751c3e46f5 100644 --- a/solution/3100-3199/3123.Find Edges in Shortest Paths/README.md +++ b/solution/3100-3199/3123.Find Edges in Shortest Paths/README.md @@ -68,24 +68,219 @@ ## 解法 -### 方法一 +### 方法一:堆优化的 Dijkstra + +我们先创建一个邻接表 $g$,用于存储图的边。然后创建一个数组 $dist$,用于存储从节点 $0$ 到其他节点的最短距离。初始化 $dist[0] = 0$,其余节点的距离初始化为无穷大。 + +然后,我们使用 Dijkstra 算法计算从节点 $0$ 到其他节点的最短距离。具体步骤如下: + +1. 创建一个优先队列 $q$,用于存储节点的距离和节点编号,初始时将节点 $0$ 加入队列,距离为 $0$。 +2. 从队列中取出一个节点 $a$,如果 $a$ 的距离 $da$ 大于 $dist[a]$,说明 $a$ 已经被更新过了,直接跳过。 +3. 遍历节点 $a$ 的所有邻居节点 $b$,如果 $dist[b] > dist[a] + w$,则更新 $dist[b] = dist[a] + w$,并将节点 $b$ 加入队列。 +4. 重复步骤 2 和步骤 3,直到队列为空。 + +接着,我们创建一个长度为 $m$ 的答案数组 $ans$,初始时所有元素都为 $false$。如果 $dist[n - 1]$ 为无穷大,说明节点 $0$ 无法到达节点 $n - 1$,直接返回 $ans$。否则,我们从节点 $n - 1$ 开始,遍历所有的边,如果边 $(a, b, i)$ 满足 $dist[a] = dist[b] + w$,则将 $ans[i]$ 置为 $true$,并将节点 $b$ 加入队列。 + +最后,返回答案即可。 + +时间复杂度 $O(m \times \log m)$,空间复杂度 $O(n + m)$,其中 $n$ 和 $m$ 分别为节点数和边数。 ```python - +class Solution: + def findAnswer(self, n: int, edges: List[List[int]]) -> List[bool]: + g = defaultdict(list) + for i, (a, b, w) in enumerate(edges): + g[a].append((b, w, i)) + g[b].append((a, w, i)) + dist = [inf] * n + dist[0] = 0 + q = [(0, 0)] + while q: + da, a = heappop(q) + if da > dist[a]: + continue + for b, w, _ in g[a]: + if dist[b] > dist[a] + w: + dist[b] = dist[a] + w + heappush(q, (dist[b], b)) + m = len(edges) + ans = [False] * m + if dist[n - 1] == inf: + return ans + q = deque([n - 1]) + while q: + a = q.popleft() + for b, w, i in g[a]: + if dist[a] == dist[b] + w: + ans[i] = True + q.append(b) + return ans ``` ```java - +class Solution { + public boolean[] findAnswer(int n, int[][] edges) { + List[] g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + int m = edges.length; + for (int i = 0; i < m; ++i) { + int a = edges[i][0], b = edges[i][1], w = edges[i][2]; + g[a].add(new int[] {b, w, i}); + g[b].add(new int[] {a, w, i}); + } + int[] dist = new int[n]; + final int inf = 1 << 30; + Arrays.fill(dist, inf); + dist[0] = 0; + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[0] - b[0]); + pq.offer(new int[] {0, 0}); + while (!pq.isEmpty()) { + var p = pq.poll(); + int da = p[0], a = p[1]; + if (da > dist[a]) { + continue; + } + for (var e : g[a]) { + int b = e[0], w = e[1]; + if (dist[b] > dist[a] + w) { + dist[b] = dist[a] + w; + pq.offer(new int[] {dist[b], b}); + } + } + } + boolean[] ans = new boolean[m]; + if (dist[n - 1] == inf) { + return ans; + } + Deque q = new ArrayDeque<>(); + q.offer(n - 1); + while (!q.isEmpty()) { + int a = q.poll(); + for (var e : g[a]) { + int b = e[0], w = e[1], i = e[2]; + if (dist[a] == dist[b] + w) { + ans[i] = true; + q.offer(b); + } + } + } + return ans; + } +} ``` ```cpp - +class Solution { +public: + vector findAnswer(int n, vector>& edges) { + vector>> g(n); + int m = edges.size(); + for (int i = 0; i < m; ++i) { + auto e = edges[i]; + int a = e[0], b = e[1], w = e[2]; + g[a].push_back({b, w, i}); + g[b].push_back({a, w, i}); + } + const int inf = 1 << 30; + vector dist(n, inf); + dist[0] = 0; + + using pii = pair; + priority_queue, greater> pq; + pq.push({0, 0}); + + while (!pq.empty()) { + auto [da, a] = pq.top(); + pq.pop(); + if (da > dist[a]) { + continue; + } + + for (auto [b, w, _] : g[a]) { + if (dist[b] > dist[a] + w) { + dist[b] = dist[a] + w; + pq.push({dist[b], b}); + } + } + } + vector ans(m); + if (dist[n - 1] == inf) { + return ans; + } + queue q{{n - 1}}; + while (!q.empty()) { + int a = q.front(); + q.pop(); + for (auto [b, w, i] : g[a]) { + if (dist[a] == dist[b] + w) { + ans[i] = true; + q.push(b); + } + } + } + return ans; + } +}; ``` ```go - +func findAnswer(n int, edges [][]int) []bool { + g := make([][][3]int, n) + for i, e := range edges { + a, b, w := e[0], e[1], e[2] + g[a] = append(g[a], [3]int{b, w, i}) + g[b] = append(g[b], [3]int{a, w, i}) + } + dist := make([]int, n) + const inf int = 1 << 30 + for i := range dist { + dist[i] = inf + } + dist[0] = 0 + pq := hp{{0, 0}} + for len(pq) > 0 { + p := heap.Pop(&pq).(pair) + da, a := p.dis, p.u + if da > dist[a] { + continue + } + for _, e := range g[a] { + b, w := e[0], e[1] + if dist[b] > dist[a]+w { + dist[b] = dist[a] + w + heap.Push(&pq, pair{dist[b], b}) + } + } + } + ans := make([]bool, len(edges)) + if dist[n-1] == inf { + return ans + } + q := []int{n - 1} + for len(q) > 0 { + a := q[0] + q = q[1:] + for _, e := range g[a] { + b, w, i := e[0], e[1], e[2] + if dist[a] == dist[b]+w { + ans[i] = true + q = append(q, b) + } + } + } + return ans +} + +type pair struct{ dis, u int } +type hp []pair + +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { return h[i].dis < h[j].dis } +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } +func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } ``` diff --git a/solution/3100-3199/3123.Find Edges in Shortest Paths/README_EN.md b/solution/3100-3199/3123.Find Edges in Shortest Paths/README_EN.md index 319afed5291c4..ac16b61d74df5 100644 --- a/solution/3100-3199/3123.Find Edges in Shortest Paths/README_EN.md +++ b/solution/3100-3199/3123.Find Edges in Shortest Paths/README_EN.md @@ -60,24 +60,219 @@ ## Solutions -### Solution 1 +### Solution 1: Heap Optimized Dijkstra + +First, we create an adjacency list $g$ to store the edges of the graph. Then we create an array $dist$ to store the shortest distance from node $0$ to other nodes. We initialize $dist[0] = 0$, and the distance of other nodes is initialized to infinity. + +Then, we use the Dijkstra algorithm to calculate the shortest distance from node $0$ to other nodes. The specific steps are as follows: + +1. Create a priority queue $q$ to store the distance and node number of the nodes. Initially, add node $0$ to the queue with a distance of $0$. +2. Take a node $a$ from the queue. If the distance $da$ of $a$ is greater than $dist[a]$, it means that $a$ has been updated, so skip it directly. +3. Traverse all neighbor nodes $b$ of node $a$. If $dist[b] > dist[a] + w$, update $dist[b] = dist[a] + w$, and add node $b$ to the queue. +4. Repeat steps 2 and 3 until the queue is empty. + +Next, we create an answer array $ans$ of length $m$, initially all elements are $false$. If $dist[n - 1]$ is infinity, it means that node $0$ cannot reach node $n - 1$, return $ans$ directly. Otherwise, we start from node $n - 1$, traverse all edges, if the edge $(a, b, i)$ satisfies $dist[a] = dist[b] + w$, set $ans[i]$ to $true$, and add node $b$ to the queue. + +Finally, return the answer. + +The time complexity is $O(m \times \log m)$, and the space complexity is $O(n + m)$, where $n$ and $m$ are the number of nodes and edges respectively. ```python - +class Solution: + def findAnswer(self, n: int, edges: List[List[int]]) -> List[bool]: + g = defaultdict(list) + for i, (a, b, w) in enumerate(edges): + g[a].append((b, w, i)) + g[b].append((a, w, i)) + dist = [inf] * n + dist[0] = 0 + q = [(0, 0)] + while q: + da, a = heappop(q) + if da > dist[a]: + continue + for b, w, _ in g[a]: + if dist[b] > dist[a] + w: + dist[b] = dist[a] + w + heappush(q, (dist[b], b)) + m = len(edges) + ans = [False] * m + if dist[n - 1] == inf: + return ans + q = deque([n - 1]) + while q: + a = q.popleft() + for b, w, i in g[a]: + if dist[a] == dist[b] + w: + ans[i] = True + q.append(b) + return ans ``` ```java - +class Solution { + public boolean[] findAnswer(int n, int[][] edges) { + List[] g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + int m = edges.length; + for (int i = 0; i < m; ++i) { + int a = edges[i][0], b = edges[i][1], w = edges[i][2]; + g[a].add(new int[] {b, w, i}); + g[b].add(new int[] {a, w, i}); + } + int[] dist = new int[n]; + final int inf = 1 << 30; + Arrays.fill(dist, inf); + dist[0] = 0; + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[0] - b[0]); + pq.offer(new int[] {0, 0}); + while (!pq.isEmpty()) { + var p = pq.poll(); + int da = p[0], a = p[1]; + if (da > dist[a]) { + continue; + } + for (var e : g[a]) { + int b = e[0], w = e[1]; + if (dist[b] > dist[a] + w) { + dist[b] = dist[a] + w; + pq.offer(new int[] {dist[b], b}); + } + } + } + boolean[] ans = new boolean[m]; + if (dist[n - 1] == inf) { + return ans; + } + Deque q = new ArrayDeque<>(); + q.offer(n - 1); + while (!q.isEmpty()) { + int a = q.poll(); + for (var e : g[a]) { + int b = e[0], w = e[1], i = e[2]; + if (dist[a] == dist[b] + w) { + ans[i] = true; + q.offer(b); + } + } + } + return ans; + } +} ``` ```cpp +class Solution { +public: + vector findAnswer(int n, vector>& edges) { + vector>> g(n); + int m = edges.size(); + for (int i = 0; i < m; ++i) { + auto e = edges[i]; + int a = e[0], b = e[1], w = e[2]; + g[a].push_back({b, w, i}); + g[b].push_back({a, w, i}); + } + const int inf = 1 << 30; + vector dist(n, inf); + dist[0] = 0; + + using pii = pair; + priority_queue, greater> pq; + pq.push({0, 0}); + while (!pq.empty()) { + auto [da, a] = pq.top(); + pq.pop(); + if (da > dist[a]) { + continue; + } + + for (auto [b, w, _] : g[a]) { + if (dist[b] > dist[a] + w) { + dist[b] = dist[a] + w; + pq.push({dist[b], b}); + } + } + } + vector ans(m); + if (dist[n - 1] == inf) { + return ans; + } + queue q{{n - 1}}; + while (!q.empty()) { + int a = q.front(); + q.pop(); + for (auto [b, w, i] : g[a]) { + if (dist[a] == dist[b] + w) { + ans[i] = true; + q.push(b); + } + } + } + return ans; + } +}; ``` ```go +func findAnswer(n int, edges [][]int) []bool { + g := make([][][3]int, n) + for i, e := range edges { + a, b, w := e[0], e[1], e[2] + g[a] = append(g[a], [3]int{b, w, i}) + g[b] = append(g[b], [3]int{a, w, i}) + } + dist := make([]int, n) + const inf int = 1 << 30 + for i := range dist { + dist[i] = inf + } + dist[0] = 0 + pq := hp{{0, 0}} + for len(pq) > 0 { + p := heap.Pop(&pq).(pair) + da, a := p.dis, p.u + if da > dist[a] { + continue + } + for _, e := range g[a] { + b, w := e[0], e[1] + if dist[b] > dist[a]+w { + dist[b] = dist[a] + w + heap.Push(&pq, pair{dist[b], b}) + } + } + } + ans := make([]bool, len(edges)) + if dist[n-1] == inf { + return ans + } + q := []int{n - 1} + for len(q) > 0 { + a := q[0] + q = q[1:] + for _, e := range g[a] { + b, w, i := e[0], e[1], e[2] + if dist[a] == dist[b]+w { + ans[i] = true + q = append(q, b) + } + } + } + return ans +} + +type pair struct{ dis, u int } +type hp []pair +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { return h[i].dis < h[j].dis } +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } +func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } ``` diff --git a/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.cpp b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.cpp new file mode 100644 index 0000000000000..d01c69e60543b --- /dev/null +++ b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.cpp @@ -0,0 +1,51 @@ +class Solution { +public: + vector findAnswer(int n, vector>& edges) { + vector>> g(n); + int m = edges.size(); + for (int i = 0; i < m; ++i) { + auto e = edges[i]; + int a = e[0], b = e[1], w = e[2]; + g[a].push_back({b, w, i}); + g[b].push_back({a, w, i}); + } + const int inf = 1 << 30; + vector dist(n, inf); + dist[0] = 0; + + using pii = pair; + priority_queue, greater> pq; + pq.push({0, 0}); + + while (!pq.empty()) { + auto [da, a] = pq.top(); + pq.pop(); + if (da > dist[a]) { + continue; + } + + for (auto [b, w, _] : g[a]) { + if (dist[b] > dist[a] + w) { + dist[b] = dist[a] + w; + pq.push({dist[b], b}); + } + } + } + vector ans(m); + if (dist[n - 1] == inf) { + return ans; + } + queue q{{n - 1}}; + while (!q.empty()) { + int a = q.front(); + q.pop(); + for (auto [b, w, i] : g[a]) { + if (dist[a] == dist[b] + w) { + ans[i] = true; + q.push(b); + } + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.go b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.go new file mode 100644 index 0000000000000..92bbb34f52425 --- /dev/null +++ b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.go @@ -0,0 +1,55 @@ +func findAnswer(n int, edges [][]int) []bool { + g := make([][][3]int, n) + for i, e := range edges { + a, b, w := e[0], e[1], e[2] + g[a] = append(g[a], [3]int{b, w, i}) + g[b] = append(g[b], [3]int{a, w, i}) + } + dist := make([]int, n) + const inf int = 1 << 30 + for i := range dist { + dist[i] = inf + } + dist[0] = 0 + pq := hp{{0, 0}} + for len(pq) > 0 { + p := heap.Pop(&pq).(pair) + da, a := p.dis, p.u + if da > dist[a] { + continue + } + for _, e := range g[a] { + b, w := e[0], e[1] + if dist[b] > dist[a]+w { + dist[b] = dist[a] + w + heap.Push(&pq, pair{dist[b], b}) + } + } + } + ans := make([]bool, len(edges)) + if dist[n-1] == inf { + return ans + } + q := []int{n - 1} + for len(q) > 0 { + a := q[0] + q = q[1:] + for _, e := range g[a] { + b, w, i := e[0], e[1], e[2] + if dist[a] == dist[b]+w { + ans[i] = true + q = append(q, b) + } + } + } + return ans +} + +type pair struct{ dis, u int } +type hp []pair + +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { return h[i].dis < h[j].dis } +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } +func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } \ No newline at end of file diff --git a/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.java b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.java new file mode 100644 index 0000000000000..f1ba9ec0ea83f --- /dev/null +++ b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.java @@ -0,0 +1,49 @@ +class Solution { + public boolean[] findAnswer(int n, int[][] edges) { + List[] g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + int m = edges.length; + for (int i = 0; i < m; ++i) { + int a = edges[i][0], b = edges[i][1], w = edges[i][2]; + g[a].add(new int[] {b, w, i}); + g[b].add(new int[] {a, w, i}); + } + int[] dist = new int[n]; + final int inf = 1 << 30; + Arrays.fill(dist, inf); + dist[0] = 0; + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[0] - b[0]); + pq.offer(new int[] {0, 0}); + while (!pq.isEmpty()) { + var p = pq.poll(); + int da = p[0], a = p[1]; + if (da > dist[a]) { + continue; + } + for (var e : g[a]) { + int b = e[0], w = e[1]; + if (dist[b] > dist[a] + w) { + dist[b] = dist[a] + w; + pq.offer(new int[] {dist[b], b}); + } + } + } + boolean[] ans = new boolean[m]; + if (dist[n - 1] == inf) { + return ans; + } + Deque q = new ArrayDeque<>(); + q.offer(n - 1); + while (!q.isEmpty()) { + int a = q.poll(); + for (var e : g[a]) { + int b = e[0], w = e[1], i = e[2]; + if (dist[a] == dist[b] + w) { + ans[i] = true; + q.offer(b); + } + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.py b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.py new file mode 100644 index 0000000000000..90493521da960 --- /dev/null +++ b/solution/3100-3199/3123.Find Edges in Shortest Paths/Solution.py @@ -0,0 +1,29 @@ +class Solution: + def findAnswer(self, n: int, edges: List[List[int]]) -> List[bool]: + g = defaultdict(list) + for i, (a, b, w) in enumerate(edges): + g[a].append((b, w, i)) + g[b].append((a, w, i)) + dist = [inf] * n + dist[0] = 0 + q = [(0, 0)] + while q: + da, a = heappop(q) + if da > dist[a]: + continue + for b, w, _ in g[a]: + if dist[b] > dist[a] + w: + dist[b] = dist[a] + w + heappush(q, (dist[b], b)) + m = len(edges) + ans = [False] * m + if dist[n - 1] == inf: + return ans + q = deque([n - 1]) + while q: + a = q.popleft() + for b, w, i in g[a]: + if dist[a] == dist[b] + w: + ans[i] = True + q.append(b) + return ans