diff --git "a/lcof/\351\235\242\350\257\225\351\242\23056 - II. \346\225\260\347\273\204\344\270\255\346\225\260\345\255\227\345\207\272\347\216\260\347\232\204\346\254\241\346\225\260 II/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23056 - II. \346\225\260\347\273\204\344\270\255\346\225\260\345\255\227\345\207\272\347\216\260\347\232\204\346\254\241\346\225\260 II/README.md" index 199a56c1c4f20..836994df5b95e 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23056 - II. \346\225\260\347\273\204\344\270\255\346\225\260\345\255\227\345\207\272\347\216\260\347\232\204\346\254\241\346\225\260 II/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23056 - II. \346\225\260\347\273\204\344\270\255\346\225\260\345\255\227\345\207\272\347\216\260\347\232\204\346\254\241\346\225\260 II/README.md" @@ -208,7 +208,7 @@ public class Solution { class Solution { func singleNumber(_ nums: [Int]) -> Int { var bitCounts = [Int](repeating: 0, count: 32) - + for num in nums { var x = num for i in 0..<32 { @@ -216,14 +216,14 @@ class Solution { x >>= 1 } } - + var result = 0 for i in 0..<32 { if bitCounts[i] % 3 == 1 { result |= 1 << i } } - + return result } } diff --git "a/lcof/\351\235\242\350\257\225\351\242\23057 - II. \345\222\214\344\270\272s\347\232\204\350\277\236\347\273\255\346\255\243\346\225\260\345\272\217\345\210\227/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23057 - II. \345\222\214\344\270\272s\347\232\204\350\277\236\347\273\255\346\255\243\346\225\260\345\272\217\345\210\227/README.md" index cff050c6eeae8..a655913f29e83 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23057 - II. \345\222\214\344\270\272s\347\232\204\350\277\236\347\273\255\346\255\243\346\225\260\345\272\217\345\210\227/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23057 - II. \345\222\214\344\270\272s\347\232\204\350\277\236\347\273\255\346\255\243\346\225\260\345\272\217\345\210\227/README.md" @@ -218,7 +218,7 @@ class Solution { func findContinuousSequence(_ target: Int) -> [[Int]] { var l = 1, r = 2 var result = [[Int]]() - + while l < r { let sum = (l + r) * (r - l + 1) / 2 if sum == target { @@ -234,7 +234,7 @@ class Solution { l += 1 } } - + return result } } diff --git "a/lcof/\351\235\242\350\257\225\351\242\23057. \345\222\214\344\270\272s\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23057. \345\222\214\344\270\272s\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227/README.md" index eb583a565660c..e492624b94524 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23057. \345\222\214\344\270\272s\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23057. \345\222\214\344\270\272s\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227/README.md" @@ -219,7 +219,7 @@ class Solution { func twoSum(_ nums: [Int], _ target: Int) -> [Int] { var l = 0 var r = nums.count - 1 - + while l < r { let sum = nums[l] + nums[r] if sum == target { @@ -230,7 +230,7 @@ class Solution { l += 1 } } - + return [] } } diff --git "a/lcof/\351\235\242\350\257\225\351\242\23058 - I. \347\277\273\350\275\254\345\215\225\350\257\215\351\241\272\345\272\217/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23058 - I. \347\277\273\350\275\254\345\215\225\350\257\215\351\241\272\345\272\217/README.md" index 6d805cc39c9bf..05ab8ebd5c7b6 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23058 - I. \347\277\273\350\275\254\345\215\225\350\257\215\351\241\272\345\272\217/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23058 - I. \347\277\273\350\275\254\345\215\225\350\257\215\351\241\272\345\272\217/README.md" @@ -258,7 +258,7 @@ class Solution { func reverseWords(_ s: String) -> String { var words = [String]() var i = s.startIndex - + while i < s.endIndex { while i < s.endIndex && s[i] == " " { i = s.index(after: i) @@ -274,7 +274,7 @@ class Solution { i = j } } - + words.reverse() return words.joined(separator: " ") } diff --git "a/lcof/\351\235\242\350\257\225\351\242\23059 - I. \346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23059 - I. \346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/README.md" index 60272c9f4d074..6f82cbaa27d87 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23059 - I. \346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23059 - I. \346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/README.md" @@ -262,23 +262,23 @@ class Solution { let n = nums.count var ans = [Int]() var deque = [Int]() - + for i in 0..= k - 1 { ans.append(nums[deque.first!]) } } - + return ans } } diff --git "a/lcof/\351\235\242\350\257\225\351\242\23059 - II. \351\230\237\345\210\227\347\232\204\346\234\200\345\244\247\345\200\274/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23059 - II. \351\230\237\345\210\227\347\232\204\346\234\200\345\244\247\345\200\274/README.md" index 660a5d6e3e321..da9e316a220bb 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23059 - II. \351\230\237\345\210\227\347\232\204\346\234\200\345\244\247\345\200\274/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23059 - II. \351\230\237\345\210\227\347\232\204\346\234\200\345\244\247\345\200\274/README.md" @@ -428,14 +428,14 @@ public class MaxQueue { class MaxQueue { private var q1: [Int] = [] private var q2: [Int] = [] - + init() { } - + func max_value() -> Int { return q2.isEmpty ? -1 : q2.first! } - + func push_back(_ value: Int) { q1.append(value) while !q2.isEmpty && q2.last! < value { @@ -443,7 +443,7 @@ class MaxQueue { } q2.append(value) } - + func pop_front() -> Int { if q1.isEmpty { return -1 diff --git a/solution/3100-3199/3167.Better Compression of String/README.md b/solution/3100-3199/3167.Better Compression of String/README.md new file mode 100644 index 0000000000000..7ca63562f1426 --- /dev/null +++ b/solution/3100-3199/3167.Better Compression of String/README.md @@ -0,0 +1,220 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3167.Better%20Compression%20of%20String/README.md +--- + + + +# [3167. Better Compression of String 🔒](https://leetcode.cn/problems/better-compression-of-string) + +[English Version](/solution/3100-3199/3167.Better%20Compression%20of%20String/README_EN.md) + +## 题目描述 + + + +

You are given a string compressed representing a compressed version of a string. The format is a character followed by its frequency. For example, "a3b1a1c2" is a compressed version of the string "aaabacc".

+ +

We seek a better compression with the following conditions:

+ +
    +
  1. Each character should appear only once in the compressed version.
  2. +
  3. The characters should be in alphabetical order.
  4. +
+ +

Return the better compression of compressed.

+ +

Note: In the better version of compression, the order of letters may change, which is acceptable.

+ +

 

+

Example 1:

+ +
+

Input: compressed = "a3c9b2c1"

+ +

Output: "a3b2c10"

+ +

Explanation:

+ +

Characters "a" and "b" appear only once in the input, but "c" appears twice, once with a size of 9 and once with a size of 1.

+ +

Hence, in the resulting string, it should have a size of 10.

+
+ +

Example 2:

+ +
+

Input: compressed = "c2b3a1"

+ +

Output: "a1b3c2"

+
+ +

Example 3:

+ +
+

Input: compressed = "a2b4c1"

+ +

Output: "a2b4c1"

+
+ +

 

+

Constraints:

+ + + + + +## 解法 + + + +### 方法一:哈希表 + 双指针 + +我们可以使用哈希表来统计每个字符的频率,然后使用双指针来遍历 `compressed` 字符串,将每个字符的频率累加到哈希表中,最后按照字母顺序将字符和频率拼接成字符串。 + +时间复杂度 $O(n + |\Sigma| \log |\Sigma|)$,空间复杂度 $O(|\Sigma|)$,其中 $n$ 是字符串 `compressed` 的长度,而 $|\Sigma|$ 是字符集的大小,这里字符集是小写字母,所以 $|\Sigma| = 26$。 + + + +#### Python3 + +```python +class Solution: + def betterCompression(self, compressed: str) -> str: + cnt = Counter() + i, n = 0, len(compressed) + while i < n: + j = i + 1 + x = 0 + while j < n and compressed[j].isdigit(): + x = x * 10 + int(compressed[j]) + j += 1 + cnt[compressed[i]] += x + i = j + return "".join(sorted(f"{k}{v}" for k, v in cnt.items())) +``` + +#### Java + +```java +class Solution { + public String betterCompression(String compressed) { + Map cnt = new TreeMap<>(); + int i = 0; + int n = compressed.length(); + while (i < n) { + char c = compressed.charAt(i); + int j = i + 1; + int x = 0; + while (j < n && Character.isDigit(compressed.charAt(j))) { + x = x * 10 + (compressed.charAt(j) - '0'); + j++; + } + cnt.merge(c, x, Integer::sum); + i = j; + } + StringBuilder ans = new StringBuilder(); + for (var e : cnt.entrySet()) { + ans.append(e.getKey()).append(e.getValue()); + } + return ans.toString(); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string betterCompression(string compressed) { + map cnt; + int i = 0; + int n = compressed.length(); + while (i < n) { + char c = compressed[i]; + int j = i + 1; + int x = 0; + while (j < n && isdigit(compressed[j])) { + x = x * 10 + (compressed[j] - '0'); + j++; + } + cnt[c] += x; + i = j; + } + stringstream ans; + for (const auto& entry : cnt) { + ans << entry.first << entry.second; + } + return ans.str(); + } +}; +``` + +#### Go + +```go +func betterCompression(compressed string) string { + cnt := map[byte]int{} + n := len(compressed) + for i := 0; i < n; { + c := compressed[i] + j := i + 1 + x := 0 + for j < n && compressed[j] >= '0' && compressed[j] <= '9' { + x = x*10 + int(compressed[j]-'0') + j++ + } + cnt[c] += x + i = j + } + ans := strings.Builder{} + for c := byte('a'); c <= byte('z'); c++ { + if cnt[c] > 0 { + ans.WriteByte(c) + ans.WriteString(strconv.Itoa(cnt[c])) + } + } + return ans.String() +} +``` + +#### TypeScript + +```ts +function betterCompression(compressed: string): string { + const cnt = new Map(); + const n = compressed.length; + let i = 0; + + while (i < n) { + const c = compressed[i]; + let j = i + 1; + let x = 0; + while (j < n && /\d/.test(compressed[j])) { + x = x * 10 + +compressed[j]; + j++; + } + cnt.set(c, (cnt.get(c) || 0) + x); + i = j; + } + const keys = Array.from(cnt.keys()).sort(); + const ans: string[] = []; + for (const k of keys) { + ans.push(`${k}${cnt.get(k)}`); + } + return ans.join(''); +} +``` + + + + + + diff --git a/solution/3100-3199/3167.Better Compression of String/README_EN.md b/solution/3100-3199/3167.Better Compression of String/README_EN.md new file mode 100644 index 0000000000000..7ab44591db6eb --- /dev/null +++ b/solution/3100-3199/3167.Better Compression of String/README_EN.md @@ -0,0 +1,220 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3167.Better%20Compression%20of%20String/README_EN.md +--- + + + +# [3167. Better Compression of String 🔒](https://leetcode.com/problems/better-compression-of-string) + +[中文文档](/solution/3100-3199/3167.Better%20Compression%20of%20String/README.md) + +## Description + + + +

You are given a string compressed representing a compressed version of a string. The format is a character followed by its frequency. For example, "a3b1a1c2" is a compressed version of the string "aaabacc".

+ +

We seek a better compression with the following conditions:

+ +
    +
  1. Each character should appear only once in the compressed version.
  2. +
  3. The characters should be in alphabetical order.
  4. +
+ +

Return the better compression of compressed.

+ +

Note: In the better version of compression, the order of letters may change, which is acceptable.

+ +

 

+

Example 1:

+ +
+

Input: compressed = "a3c9b2c1"

+ +

Output: "a3b2c10"

+ +

Explanation:

+ +

Characters "a" and "b" appear only once in the input, but "c" appears twice, once with a size of 9 and once with a size of 1.

+ +

Hence, in the resulting string, it should have a size of 10.

+
+ +

Example 2:

+ +
+

Input: compressed = "c2b3a1"

+ +

Output: "a1b3c2"

+
+ +

Example 3:

+ +
+

Input: compressed = "a2b4c1"

+ +

Output: "a2b4c1"

+
+ +

 

+

Constraints:

+ +
    +
  • 1 <= compressed.length <= 6 * 104
  • +
  • compressed consists only of lowercase English letters and digits.
  • +
  • compressed is a valid compression, i.e., each character is followed by its frequency.
  • +
  • Frequencies are in the range [1, 104] and have no leading zeroes.
  • +
+ + + +## Solutions + + + +### Solution 1: Hash Table + Two Pointers + +We can use a hash table to count the frequency of each character, and then use two pointers to traverse the `compressed` string, adding the frequency of each character to the hash table. Finally, we concatenate the characters and frequencies into a string in alphabetical order. + +The time complexity is $O(n + |\Sigma| \log |\Sigma|)$, and the space complexity is $O(|\Sigma|)$. Where $n$ is the length of the string `compressed`, and $|\Sigma|$ is the size of the character set. Here, the character set is lowercase letters, so $|\Sigma| = 26$. + + + +#### Python3 + +```python +class Solution: + def betterCompression(self, compressed: str) -> str: + cnt = Counter() + i, n = 0, len(compressed) + while i < n: + j = i + 1 + x = 0 + while j < n and compressed[j].isdigit(): + x = x * 10 + int(compressed[j]) + j += 1 + cnt[compressed[i]] += x + i = j + return "".join(sorted(f"{k}{v}" for k, v in cnt.items())) +``` + +#### Java + +```java +class Solution { + public String betterCompression(String compressed) { + Map cnt = new TreeMap<>(); + int i = 0; + int n = compressed.length(); + while (i < n) { + char c = compressed.charAt(i); + int j = i + 1; + int x = 0; + while (j < n && Character.isDigit(compressed.charAt(j))) { + x = x * 10 + (compressed.charAt(j) - '0'); + j++; + } + cnt.merge(c, x, Integer::sum); + i = j; + } + StringBuilder ans = new StringBuilder(); + for (var e : cnt.entrySet()) { + ans.append(e.getKey()).append(e.getValue()); + } + return ans.toString(); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string betterCompression(string compressed) { + map cnt; + int i = 0; + int n = compressed.length(); + while (i < n) { + char c = compressed[i]; + int j = i + 1; + int x = 0; + while (j < n && isdigit(compressed[j])) { + x = x * 10 + (compressed[j] - '0'); + j++; + } + cnt[c] += x; + i = j; + } + stringstream ans; + for (const auto& entry : cnt) { + ans << entry.first << entry.second; + } + return ans.str(); + } +}; +``` + +#### Go + +```go +func betterCompression(compressed string) string { + cnt := map[byte]int{} + n := len(compressed) + for i := 0; i < n; { + c := compressed[i] + j := i + 1 + x := 0 + for j < n && compressed[j] >= '0' && compressed[j] <= '9' { + x = x*10 + int(compressed[j]-'0') + j++ + } + cnt[c] += x + i = j + } + ans := strings.Builder{} + for c := byte('a'); c <= byte('z'); c++ { + if cnt[c] > 0 { + ans.WriteByte(c) + ans.WriteString(strconv.Itoa(cnt[c])) + } + } + return ans.String() +} +``` + +#### TypeScript + +```ts +function betterCompression(compressed: string): string { + const cnt = new Map(); + const n = compressed.length; + let i = 0; + + while (i < n) { + const c = compressed[i]; + let j = i + 1; + let x = 0; + while (j < n && /\d/.test(compressed[j])) { + x = x * 10 + +compressed[j]; + j++; + } + cnt.set(c, (cnt.get(c) || 0) + x); + i = j; + } + const keys = Array.from(cnt.keys()).sort(); + const ans: string[] = []; + for (const k of keys) { + ans.push(`${k}${cnt.get(k)}`); + } + return ans.join(''); +} +``` + + + + + + diff --git a/solution/3100-3199/3167.Better Compression of String/Solution.cpp b/solution/3100-3199/3167.Better Compression of String/Solution.cpp new file mode 100644 index 0000000000000..59034d04c2683 --- /dev/null +++ b/solution/3100-3199/3167.Better Compression of String/Solution.cpp @@ -0,0 +1,24 @@ +class Solution { +public: + string betterCompression(string compressed) { + map cnt; + int i = 0; + int n = compressed.length(); + while (i < n) { + char c = compressed[i]; + int j = i + 1; + int x = 0; + while (j < n && isdigit(compressed[j])) { + x = x * 10 + (compressed[j] - '0'); + j++; + } + cnt[c] += x; + i = j; + } + stringstream ans; + for (const auto& entry : cnt) { + ans << entry.first << entry.second; + } + return ans.str(); + } +}; \ No newline at end of file diff --git a/solution/3100-3199/3167.Better Compression of String/Solution.go b/solution/3100-3199/3167.Better Compression of String/Solution.go new file mode 100644 index 0000000000000..b751ec17510b0 --- /dev/null +++ b/solution/3100-3199/3167.Better Compression of String/Solution.go @@ -0,0 +1,23 @@ +func betterCompression(compressed string) string { + cnt := map[byte]int{} + n := len(compressed) + for i := 0; i < n; { + c := compressed[i] + j := i + 1 + x := 0 + for j < n && compressed[j] >= '0' && compressed[j] <= '9' { + x = x*10 + int(compressed[j]-'0') + j++ + } + cnt[c] += x + i = j + } + ans := strings.Builder{} + for c := byte('a'); c <= byte('z'); c++ { + if cnt[c] > 0 { + ans.WriteByte(c) + ans.WriteString(strconv.Itoa(cnt[c])) + } + } + return ans.String() +} \ No newline at end of file diff --git a/solution/3100-3199/3167.Better Compression of String/Solution.java b/solution/3100-3199/3167.Better Compression of String/Solution.java new file mode 100644 index 0000000000000..4320e752537d3 --- /dev/null +++ b/solution/3100-3199/3167.Better Compression of String/Solution.java @@ -0,0 +1,23 @@ +class Solution { + public String betterCompression(String compressed) { + Map cnt = new TreeMap<>(); + int i = 0; + int n = compressed.length(); + while (i < n) { + char c = compressed.charAt(i); + int j = i + 1; + int x = 0; + while (j < n && Character.isDigit(compressed.charAt(j))) { + x = x * 10 + (compressed.charAt(j) - '0'); + j++; + } + cnt.merge(c, x, Integer::sum); + i = j; + } + StringBuilder ans = new StringBuilder(); + for (var e : cnt.entrySet()) { + ans.append(e.getKey()).append(e.getValue()); + } + return ans.toString(); + } +} \ No newline at end of file diff --git a/solution/3100-3199/3167.Better Compression of String/Solution.py b/solution/3100-3199/3167.Better Compression of String/Solution.py new file mode 100644 index 0000000000000..a49e67c7ed3d9 --- /dev/null +++ b/solution/3100-3199/3167.Better Compression of String/Solution.py @@ -0,0 +1,13 @@ +class Solution: + def betterCompression(self, compressed: str) -> str: + cnt = Counter() + i, n = 0, len(compressed) + while i < n: + j = i + 1 + x = 0 + while j < n and compressed[j].isdigit(): + x = x * 10 + int(compressed[j]) + j += 1 + cnt[compressed[i]] += x + i = j + return "".join(sorted(f"{k}{v}" for k, v in cnt.items())) diff --git a/solution/3100-3199/3167.Better Compression of String/Solution.ts b/solution/3100-3199/3167.Better Compression of String/Solution.ts new file mode 100644 index 0000000000000..a1c3e14123624 --- /dev/null +++ b/solution/3100-3199/3167.Better Compression of String/Solution.ts @@ -0,0 +1,23 @@ +function betterCompression(compressed: string): string { + const cnt = new Map(); + const n = compressed.length; + let i = 0; + + while (i < n) { + const c = compressed[i]; + let j = i + 1; + let x = 0; + while (j < n && /\d/.test(compressed[j])) { + x = x * 10 + +compressed[j]; + j++; + } + cnt.set(c, (cnt.get(c) || 0) + x); + i = j; + } + const keys = Array.from(cnt.keys()).sort(); + const ans: string[] = []; + for (const k of keys) { + ans.push(`${k}${cnt.get(k)}`); + } + return ans.join(''); +} diff --git a/solution/README.md b/solution/README.md index d9d829b24dd9c..b0669ec5c0970 100644 --- a/solution/README.md +++ b/solution/README.md @@ -3177,6 +3177,7 @@ | 3164 | [优质数对的总数 II](/solution/3100-3199/3164.Find%20the%20Number%20of%20Good%20Pairs%20II/README.md) | | 中等 | 第 399 场周赛 | | 3165 | [不包含相邻元素的子序列的最大和](/solution/3100-3199/3165.Maximum%20Sum%20of%20Subsequence%20With%20Non-adjacent%20Elements/README.md) | | 困难 | 第 399 场周赛 | | 3166 | [计算停车费与时长](/solution/3100-3199/3166.Calculate%20Parking%20Fees%20and%20Duration/README.md) | | 中等 | 🔒 | +| 3167 | [Better Compression of String](/solution/3100-3199/3167.Better%20Compression%20of%20String/README.md) | | 中等 | 🔒 | ## 版权 diff --git a/solution/README_EN.md b/solution/README_EN.md index b3badd06df525..d2b8600a62b5d 100644 --- a/solution/README_EN.md +++ b/solution/README_EN.md @@ -3175,6 +3175,7 @@ Press Control + F(or Command + F on | 3164 | [Find the Number of Good Pairs II](/solution/3100-3199/3164.Find%20the%20Number%20of%20Good%20Pairs%20II/README_EN.md) | | Medium | Weekly Contest 399 | | 3165 | [Maximum Sum of Subsequence With Non-adjacent Elements](/solution/3100-3199/3165.Maximum%20Sum%20of%20Subsequence%20With%20Non-adjacent%20Elements/README_EN.md) | | Hard | Weekly Contest 399 | | 3166 | [Calculate Parking Fees and Duration](/solution/3100-3199/3166.Calculate%20Parking%20Fees%20and%20Duration/README_EN.md) | | Medium | 🔒 | +| 3167 | [Better Compression of String](/solution/3100-3199/3167.Better%20Compression%20of%20String/README_EN.md) | | Medium | 🔒 | ## Copyright