From d51afc4183043243acf1c2569899c153aad7e60a Mon Sep 17 00:00:00 2001 From: yanglbme Date: Thu, 28 Sep 2023 16:42:24 +0800 Subject: [PATCH 1/2] feat: update solutions to lc problems: No.2262,2264 * No.2262.Total Appeal of A String * No.2264.Largest 3-Same-Digit Number in String --- .../2262.Total Appeal of A String/README.md | 32 ++++++---- .../README_EN.md | 31 +++++++--- .../2262.Total Appeal of A String/Solution.ts | 16 ++--- .../README.md | 58 +++++++++++-------- .../README_EN.md | 50 ++++++++-------- .../Solution.cpp | 20 ++++--- .../Solution.go | 5 +- .../Solution.java | 22 +++---- .../Solution.py | 13 ++--- .../Solution.ts | 6 +- 10 files changed, 147 insertions(+), 106 deletions(-) diff --git a/solution/2200-2299/2262.Total Appeal of A String/README.md b/solution/2200-2299/2262.Total Appeal of A String/README.md index 23ab3b9b7c27d..3ae12344efe5c 100644 --- a/solution/2200-2299/2262.Total Appeal of A String/README.md +++ b/solution/2200-2299/2262.Total Appeal of A String/README.md @@ -56,14 +56,20 @@ -遍历字符串 s 每个字符 `s[i]`, 维护以 `s[i]` 结尾的子串的引力值之和 t,遍历过程中累加 t 得到结果。 +**方法一:枚举** -若当前遍历到字符 `s[i]`,对应的引力值 t 的计算逻辑为: +我们可以枚举以每个字符 $s[i]$ 结尾的字符串,计算其引力值之和 $t$,最后将所有 $t$ 相加即可。 -1. 如果 `s[i]` 在之前没出现过,那么以 `s[i-1]` 结尾的每个子串的引力值都会加上 1,引力值之和会增加 i,再加上 1(`s[i]` 单独组成的子串的引力值),得到 `s[i]` 的引力值 t。 -1. 如果 `s[i]` 在之前出现过,定义最近一次出现的下标为 j,那么向子串 `s[0..i-1], s[1..i-1], ..., s[j..i-1]` 的末尾添加 `s[i]`,引力值不变。而 `s[j+1..i-1], s[j+2..i=1], ..., s[i-1..i-1]` 由于不包含 s[i],这些子串的引力值增加 1,因此有 i-j-1 个子串的引力值会增加 1,引力值之和增加 i-j-1,再加上 1,得到 `s[i]` 的引力值 t。 +考虑遍历到 $s[i]$ 时,即把 $s[i]$ 添加到以 $s[i-1]$ 结尾的子字符串的后面,其引力值之和 $t$ 的变化情况: -此过程中,我们用 pos 记录每个字符最近一次出现的位置。 +1. 如果 $s[i]$ 在之前没出现过,那么所有以 $s[i-1]$ 结尾的子字符串的引力值都会增加 $1$,共有 $i$ 个,所以 $t$ 增加 $i$,再加上 $s[i]$ 自身的引力值 $1$,所以 $t$ 一共增加 $i+1$; +1. 如果 $s[i]$ 在之前出现过,不妨记上次出现的的位置为 $j$,那么我们向子字符串 $s[0..i-1]$, $[1..i-1]$, $s[2..i-1]$, $\cdots$, $s[j..i-1]$ 后面添加 $s[i]$,这些子字符串的引力值不会发生变化,因为 $s[i]$ 已经在这些子字符串中出现过了;而子字符串 $s[j+1..i-1]$, $s[j+2..i-1]$, $\cdots$, $s[i-1]$ 的引力值都会增加 $1$,共有 $i-j-1$ 个,所以 $t$ 增加 $i-j-1$,再加上 $s[i]$ 自身的引力值 $1$,所以 $t$ 一共增加 $i-j$。 + +综上,我们可以用一个数组 $pos$ 记录每个字符上次出现的位置,初始时所有位置都为 $-1$, + +接下来,我们遍历字符串,每一次我们更新以当前字符结尾的子字符串的引力值之和 $t = t + i - pos[c]$,其中 $c$ 是当前字符,累加 $t$ 到答案中。然后我们更新 $pos[c]$ 为当前位置 $i$。继续遍历直到字符串结束。 + +时间复杂度 $O(n)$,空间复杂度 $O(|\Sigma|)$,其中 $n$ 是字符串 $s$ 的长度;而 $|\Sigma|$ 是字符集的大小,本题中 $|\Sigma| = 26$。 @@ -148,15 +154,17 @@ func appealSum(s string) int64 { ```ts function appealSum(s: string): number { + const pos: number[] = Array(26).fill(-1); const n = s.length; - let dp = new Array(n + 1).fill(0); - const hashMap = new Map(); - for (let i = 0; i < n; i++) { - const c = s.charAt(i); - dp[i + 1] = dp[i] + i + 1 - (hashMap.get(c) || 0); - hashMap.set(c, i + 1); + let ans = 0; + let t = 0; + for (let i = 0; i < n; ++i) { + const c = s.charCodeAt(i) - 97; + t += i - pos[c]; + ans += t; + pos[c] = i; } - return dp.reduce((a, c) => a + c, 0); + return ans; } ``` diff --git a/solution/2200-2299/2262.Total Appeal of A String/README_EN.md b/solution/2200-2299/2262.Total Appeal of A String/README_EN.md index ac8b69a6e9d05..ec6322ba72ac4 100644 --- a/solution/2200-2299/2262.Total Appeal of A String/README_EN.md +++ b/solution/2200-2299/2262.Total Appeal of A String/README_EN.md @@ -52,6 +52,21 @@ The total sum is 4 + 6 + 6 + 4 = 20. ## Solutions +**Solution 1: Enumeration** + +We can enumerate all the substrings that end with each character $s[i]$ and calculate their gravitational value sum $t$. Finally, we add up all the $t$ to get the total gravitational value sum. + +When we reach $s[i]$, which is added to the end of the substring that ends with $s[i-1]$, we consider the change of the gravitational value sum $t$: + +If $s[i]$ has not appeared before, then the gravitational value of all substrings that end with $s[i-1]$ will increase by $1$, and there are a total of $i$ such substrings. Therefore, $t$ increases by $i$, plus the gravitational value of $s[i]$ itself, which is $1$. Therefore, $t$ increases by a total of $i+1$. + +If $s[i]$ has appeared before, let the last appearance position be $j$. Then we add $s[i]$ to the end of the substrings $s[0..i-1]$, $[1..i-1]$, $s[2..i-1]$, $\cdots$, $s[j..i-1]$. The gravitational value of these substrings will not change because $s[i]$ has already appeared in these substrings. The gravitational value of the substrings $s[j+1..i-1]$, $s[j+2..i-1]$, $\cdots$, $s[i-1]$ will increase by $1$, and there are a total of $i-j-1$ such substrings. Therefore, $t$ increases by $i-j-1$, plus the gravitational value of $s[i]$ itself, which is $1$. Therefore, $t$ increases by a total of $i-j$. +Therefore, we can use an array $pos$ to record the last appearance position of each character. Initially, all positions are set to $-1$. + +Next, we traverse the string, and each time we update the gravitational value sum $t$ of the substring that ends with the current character to $t = t + i - pos[c]$, where $c$ is the current character. We add $t$ to the answer. Then we update $pos[c]$ to the current position $i$. We continue to traverse until the end of the string. + +The time complexity is $O(n)$, and the space complexity is $O(|\Sigma|)$, where $n$ is the length of the string $s$, and $|\Sigma|$ is the size of the character set. In this problem, $|\Sigma| = 26$. + ### **Python3** @@ -131,15 +146,17 @@ func appealSum(s string) int64 { ```ts function appealSum(s: string): number { + const pos: number[] = Array(26).fill(-1); const n = s.length; - let dp = new Array(n + 1).fill(0); - const hashMap = new Map(); - for (let i = 0; i < n; i++) { - const c = s.charAt(i); - dp[i + 1] = dp[i] + i + 1 - (hashMap.get(c) || 0); - hashMap.set(c, i + 1); + let ans = 0; + let t = 0; + for (let i = 0; i < n; ++i) { + const c = s.charCodeAt(i) - 97; + t += i - pos[c]; + ans += t; + pos[c] = i; } - return dp.reduce((a, c) => a + c, 0); + return ans; } ``` diff --git a/solution/2200-2299/2262.Total Appeal of A String/Solution.ts b/solution/2200-2299/2262.Total Appeal of A String/Solution.ts index 24f92ba50842c..81ad5dfb99602 100644 --- a/solution/2200-2299/2262.Total Appeal of A String/Solution.ts +++ b/solution/2200-2299/2262.Total Appeal of A String/Solution.ts @@ -1,11 +1,13 @@ function appealSum(s: string): number { + const pos: number[] = Array(26).fill(-1); const n = s.length; - let dp = new Array(n + 1).fill(0); - const hashMap = new Map(); - for (let i = 0; i < n; i++) { - const c = s.charAt(i); - dp[i + 1] = dp[i] + i + 1 - (hashMap.get(c) || 0); - hashMap.set(c, i + 1); + let ans = 0; + let t = 0; + for (let i = 0; i < n; ++i) { + const c = s.charCodeAt(i) - 97; + t += i - pos[c]; + ans += t; + pos[c] = i; } - return dp.reduce((a, c) => a + c, 0); + return ans; } diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md index bd172bee944b3..b40c676a9d43b 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md @@ -62,6 +62,14 @@ +**方法一:枚举** + +我们可以从大到小枚举每个数字 $i$,其中 $0 \le i \le 9$,然后判断连续的三个 $i$ 构成的字符串 $s$ 是否是 $num$ 的子串,若是,直接返回 $s$ 即可。 + +若枚举完所有的 $i$ 都没有找到满足条件的字符串,则返回空字符串。 + +时间复杂度 $O(10) + ### **Python3** @@ -72,10 +80,9 @@ class Solution: def largestGoodInteger(self, num: str) -> str: for i in range(9, -1, -1): - t = str(i) * 3 - if t in num: - return t - return '' + if (s := str(i) * 3) in num: + return s + return "" ``` ### **Java** @@ -86,9 +93,9 @@ class Solution: class Solution { public String largestGoodInteger(String num) { for (int i = 9; i >= 0; i--) { - String ret = String.valueOf(i).repeat(3); - if (num.contains(ret)) { - return ret; + String s = String.valueOf(i).repeat(3); + if (num.contains(s)) { + return s; } } return ""; @@ -96,18 +103,6 @@ class Solution { } ``` -### **TypeScript** - -```ts -function largestGoodInteger(num: string): string { - for (let i = 9; i >= 0; i--) { - const c = String(i).repeat(3); - if (num.includes(c)) return c; - } - return ''; -} -``` - ### **C++** ```cpp @@ -115,8 +110,10 @@ class Solution { public: string largestGoodInteger(string num) { for (char i = '9'; i >= '0'; --i) { - string t(3, i); - if (num.find(t) != string::npos) return t; + string s(3, i); + if (num.find(s) != string::npos) { + return s; + } } return ""; } @@ -128,15 +125,28 @@ public: ```go func largestGoodInteger(num string) string { for c := '9'; c >= '0'; c-- { - t := strings.Repeat(string(c), 3) - if strings.Contains(num, t) { - return t + if s := strings.Repeat(string(c), 3); strings.Contains(num, s) { + return s } } return "" } ``` +### **TypeScript** + +```ts +function largestGoodInteger(num: string): string { + for (let i = 9; i >= 0; i--) { + const s = String(i).repeat(3); + if (num.includes(s)) { + return s; + } + } + return ''; +} +``` + ### **...** ``` diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md index aab1c8c6e8117..86e70b19efb2a 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md @@ -64,10 +64,9 @@ class Solution: def largestGoodInteger(self, num: str) -> str: for i in range(9, -1, -1): - t = str(i) * 3 - if t in num: - return t - return '' + if (s := str(i) * 3) in num: + return s + return "" ``` ### **Java** @@ -76,9 +75,9 @@ class Solution: class Solution { public String largestGoodInteger(String num) { for (int i = 9; i >= 0; i--) { - String ret = String.valueOf(i).repeat(3); - if (num.contains(ret)) { - return ret; + String s = String.valueOf(i).repeat(3); + if (num.contains(s)) { + return s; } } return ""; @@ -86,18 +85,6 @@ class Solution { } ``` -### **TypeScript** - -```ts -function largestGoodInteger(num: string): string { - for (let i = 9; i >= 0; i--) { - const c = String(i).repeat(3); - if (num.includes(c)) return c; - } - return ''; -} -``` - ### **C++** ```cpp @@ -105,8 +92,10 @@ class Solution { public: string largestGoodInteger(string num) { for (char i = '9'; i >= '0'; --i) { - string t(3, i); - if (num.find(t) != string::npos) return t; + string s(3, i); + if (num.find(s) != string::npos) { + return s; + } } return ""; } @@ -118,15 +107,28 @@ public: ```go func largestGoodInteger(num string) string { for c := '9'; c >= '0'; c-- { - t := strings.Repeat(string(c), 3) - if strings.Contains(num, t) { - return t + if s := strings.Repeat(string(c), 3); strings.Contains(num, s) { + return s } } return "" } ``` +### **TypeScript** + +```ts +function largestGoodInteger(num: string): string { + for (let i = 9; i >= 0; i--) { + const s = String(i).repeat(3); + if (num.includes(s)) { + return s; + } + } + return ''; +} +``` + ### **...** ``` diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.cpp b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.cpp index 2b1719c425507..a1d09fbeccb36 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.cpp +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.cpp @@ -1,10 +1,12 @@ -class Solution { -public: - string largestGoodInteger(string num) { - for (char i = '9'; i >= '0'; --i) { - string t(3, i); - if (num.find(t) != string::npos) return t; - } - return ""; - } +class Solution { +public: + string largestGoodInteger(string num) { + for (char i = '9'; i >= '0'; --i) { + string s(3, i); + if (num.find(s) != string::npos) { + return s; + } + } + return ""; + } }; \ No newline at end of file diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.go b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.go index 1c9e843cd2b02..cd155fe039e84 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.go +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.go @@ -1,8 +1,7 @@ func largestGoodInteger(num string) string { for c := '9'; c >= '0'; c-- { - t := strings.Repeat(string(c), 3) - if strings.Contains(num, t) { - return t + if s := strings.Repeat(string(c), 3); strings.Contains(num, s) { + return s } } return "" diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.java b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.java index 946f4005ad038..49684a7168919 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.java +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.java @@ -1,11 +1,11 @@ -class Solution { - public String largestGoodInteger(String num) { - for (int i = 9; i >= 0; i--) { - String ret = String.valueOf(i).repeat(3); - if (num.contains(ret)) { - return ret; - } - } - return ""; - } -} +class Solution { + public String largestGoodInteger(String num) { + for (int i = 9; i >= 0; i--) { + String s = String.valueOf(i).repeat(3); + if (num.contains(s)) { + return s; + } + } + return ""; + } +} diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.py b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.py index 7d91504e22280..30d2c88b8b4fc 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.py +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.py @@ -1,7 +1,6 @@ -class Solution: - def largestGoodInteger(self, num: str) -> str: - for i in range(9, -1, -1): - t = str(i) * 3 - if t in num: - return t - return '' +class Solution: + def largestGoodInteger(self, num: str) -> str: + for i in range(9, -1, -1): + if (s := str(i) * 3) in num: + return s + return "" diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.ts b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.ts index 67065d55775c9..172992e6cda0d 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.ts +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/Solution.ts @@ -1,7 +1,9 @@ function largestGoodInteger(num: string): string { for (let i = 9; i >= 0; i--) { - const c = String(i).repeat(3); - if (num.includes(c)) return c; + const s = String(i).repeat(3); + if (num.includes(s)) { + return s; + } } return ''; } From 8420e46444efd1ef0a404ad26607f9bc05e831e2 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Thu, 28 Sep 2023 17:00:09 +0800 Subject: [PATCH 2/2] fix: readme --- .../2264.Largest 3-Same-Digit Number in String/README.md | 2 +- .../README_EN.md | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md index b40c676a9d43b..bacca86ba418e 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README.md @@ -68,7 +68,7 @@ 若枚举完所有的 $i$ 都没有找到满足条件的字符串,则返回空字符串。 -时间复杂度 $O(10) +时间复杂度 $O(10 \times n)$,其中 $n$ 是字符串 $num$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md index 86e70b19efb2a..598479bb6b9d0 100644 --- a/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md +++ b/solution/2200-2299/2264.Largest 3-Same-Digit Number in String/README_EN.md @@ -56,6 +56,14 @@ ## Solutions +**Solution 1: Enumeration** + +We can enumerate each digit $i$ from large to small, where $0 \le i \le 9$, and then check whether the string $s$ consisting of three consecutive $i$ is a substring of $num$. If it is, we directly return $s$. + +If we have enumerated all the possible values of $i$ and still haven't found a substring that satisfies the condition, we return an empty string. + +The time complexity is $O(10 \times n)$, where $n$ is the length of the string $num$. The space complexity is $O(1)$. + ### **Python3**