Skip to content

Commit 32c0fd2

Browse files
authored
feat: add solutions to lc problem: No.3167 (#2956)
No.3167.Better Compression of String
1 parent 5fe3866 commit 32c0fd2

File tree

15 files changed

+566
-18
lines changed

15 files changed

+566
-18
lines changed

lcof/面试题56 - II. 数组中数字出现的次数 II/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -208,22 +208,22 @@ public class Solution {
208208
class Solution {
209209
func singleNumber(_ nums: [Int]) -> Int {
210210
var bitCounts = [Int](repeating: 0, count: 32)
211-
211+
212212
for num in nums {
213213
var x = num
214214
for i in 0..<32 {
215215
bitCounts[i] += x & 1
216216
x >>= 1
217217
}
218218
}
219-
219+
220220
var result = 0
221221
for i in 0..<32 {
222222
if bitCounts[i] % 3 == 1 {
223223
result |= 1 << i
224224
}
225225
}
226-
226+
227227
return result
228228
}
229229
}

lcof/面试题57 - II. 和为s的连续正数序列/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class Solution {
218218
func findContinuousSequence(_ target: Int) -> [[Int]] {
219219
var l = 1, r = 2
220220
var result = [[Int]]()
221-
221+
222222
while l < r {
223223
let sum = (l + r) * (r - l + 1) / 2
224224
if sum == target {
@@ -234,7 +234,7 @@ class Solution {
234234
l += 1
235235
}
236236
}
237-
237+
238238
return result
239239
}
240240
}

lcof/面试题57. 和为s的两个数字/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class Solution {
219219
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
220220
var l = 0
221221
var r = nums.count - 1
222-
222+
223223
while l < r {
224224
let sum = nums[l] + nums[r]
225225
if sum == target {
@@ -230,7 +230,7 @@ class Solution {
230230
l += 1
231231
}
232232
}
233-
233+
234234
return []
235235
}
236236
}

lcof/面试题58 - I. 翻转单词顺序/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class Solution {
258258
func reverseWords(_ s: String) -> String {
259259
var words = [String]()
260260
var i = s.startIndex
261-
261+
262262
while i < s.endIndex {
263263
while i < s.endIndex && s[i] == " " {
264264
i = s.index(after: i)
@@ -274,7 +274,7 @@ class Solution {
274274
i = j
275275
}
276276
}
277-
277+
278278
words.reverse()
279279
return words.joined(separator: " ")
280280
}

lcof/面试题59 - I. 滑动窗口的最大值/README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -262,23 +262,23 @@ class Solution {
262262
let n = nums.count
263263
var ans = [Int]()
264264
var deque = [Int]()
265-
265+
266266
for i in 0..<n {
267267
if !deque.isEmpty && deque.first! < i - k + 1 {
268268
deque.removeFirst()
269269
}
270-
270+
271271
while !deque.isEmpty && nums[deque.last!] <= nums[i] {
272272
deque.removeLast()
273273
}
274-
274+
275275
deque.append(i)
276-
276+
277277
if i >= k - 1 {
278278
ans.append(nums[deque.first!])
279279
}
280280
}
281-
281+
282282
return ans
283283
}
284284
}

lcof/面试题59 - II. 队列的最大值/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -428,22 +428,22 @@ public class MaxQueue {
428428
class MaxQueue {
429429
private var q1: [Int] = []
430430
private var q2: [Int] = []
431-
431+
432432
init() {
433433
}
434-
434+
435435
func max_value() -> Int {
436436
return q2.isEmpty ? -1 : q2.first!
437437
}
438-
438+
439439
func push_back(_ value: Int) {
440440
q1.append(value)
441441
while !q2.isEmpty && q2.last! < value {
442442
q2.removeLast()
443443
}
444444
q2.append(value)
445445
}
446-
446+
447447
func pop_front() -> Int {
448448
if q1.isEmpty {
449449
return -1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
---
2+
comments: true
3+
difficulty: 中等
4+
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3167.Better%20Compression%20of%20String/README.md
5+
---
6+
7+
<!-- problem:start -->
8+
9+
# [3167. Better Compression of String 🔒](https://leetcode.cn/problems/better-compression-of-string)
10+
11+
[English Version](/solution/3100-3199/3167.Better%20Compression%20of%20String/README_EN.md)
12+
13+
## 题目描述
14+
15+
<!-- description:start -->
16+
17+
<p>You are given a string <code>compressed</code> representing a compressed version of a string. The format is a character followed by its frequency. For example, <code>&quot;a3b1a1c2&quot;</code> is a compressed version of the string <code>&quot;aaabacc&quot;</code>.</p>
18+
19+
<p>We seek a <strong>better compression</strong> with the following conditions:</p>
20+
21+
<ol>
22+
<li>Each character should appear <strong>only once</strong> in the compressed version.</li>
23+
<li>The characters should be in <strong>alphabetical order</strong>.</li>
24+
</ol>
25+
26+
<p>Return the <em>better compression</em> of <code>compressed</code>.</p>
27+
28+
<p><strong>Note:</strong> In the better version of compression, the order of letters may change, which is acceptable.</p>
29+
30+
<p>&nbsp;</p>
31+
<p><strong class="example">Example 1:</strong></p>
32+
33+
<div class="example-block">
34+
<p><strong>Input:</strong> <span class="example-io">compressed = &quot;a3c9b2c1&quot;</span></p>
35+
36+
<p><strong>Output:</strong> <span class="example-io">&quot;a3b2c10&quot;</span></p>
37+
38+
<p><strong>Explanation:</strong></p>
39+
40+
<p>Characters &quot;a&quot; and &quot;b&quot; appear only once in the input, but &quot;c&quot; appears twice, once with a size of 9 and once with a size of 1.</p>
41+
42+
<p>Hence, in the resulting string, it should have a size of 10.</p>
43+
</div>
44+
45+
<p><strong class="example">Example 2:</strong></p>
46+
47+
<div class="example-block">
48+
<p><strong>Input:</strong> <span class="example-io">compressed = &quot;c2b3a1&quot;</span></p>
49+
50+
<p><strong>Output:</strong> <span class="example-io">&quot;a1b3c2&quot;</span></p>
51+
</div>
52+
53+
<p><strong class="example">Example 3:</strong></p>
54+
55+
<div class="example-block">
56+
<p><strong>Input:</strong> <span class="example-io">compressed = &quot;a2b4c1&quot;</span></p>
57+
58+
<p><strong>Output:</strong> <span class="example-io">&quot;a2b4c1&quot;</span></p>
59+
</div>
60+
61+
<p>&nbsp;</p>
62+
<p><strong>Constraints:</strong></p>
63+
64+
<ul>
65+
<li><code>1 &lt;= compressed.length &lt;= 6 * 10<sup>4</sup></code></li>
66+
<li><code>compressed</code> consists only of lowercase English letters and digits.</li>
67+
<li><code>compressed</code> is a valid compression, i.e., each character is followed by its frequency.</li>
68+
<li>Frequencies are in the range <code>[1, 10<sup>4</sup>]</code> and have no leading zeroes.</li>
69+
</ul>
70+
71+
<!-- description:end -->
72+
73+
## 解法
74+
75+
<!-- solution:start -->
76+
77+
### 方法一:哈希表 + 双指针
78+
79+
我们可以使用哈希表来统计每个字符的频率,然后使用双指针来遍历 `compressed` 字符串,将每个字符的频率累加到哈希表中,最后按照字母顺序将字符和频率拼接成字符串。
80+
81+
时间复杂度 $O(n + |\Sigma| \log |\Sigma|)$,空间复杂度 $O(|\Sigma|)$,其中 $n$ 是字符串 `compressed` 的长度,而 $|\Sigma|$ 是字符集的大小,这里字符集是小写字母,所以 $|\Sigma| = 26$。
82+
83+
<!-- tabs:start -->
84+
85+
#### Python3
86+
87+
```python
88+
class Solution:
89+
def betterCompression(self, compressed: str) -> str:
90+
cnt = Counter()
91+
i, n = 0, len(compressed)
92+
while i < n:
93+
j = i + 1
94+
x = 0
95+
while j < n and compressed[j].isdigit():
96+
x = x * 10 + int(compressed[j])
97+
j += 1
98+
cnt[compressed[i]] += x
99+
i = j
100+
return "".join(sorted(f"{k}{v}" for k, v in cnt.items()))
101+
```
102+
103+
#### Java
104+
105+
```java
106+
class Solution {
107+
public String betterCompression(String compressed) {
108+
Map<Character, Integer> cnt = new TreeMap<>();
109+
int i = 0;
110+
int n = compressed.length();
111+
while (i < n) {
112+
char c = compressed.charAt(i);
113+
int j = i + 1;
114+
int x = 0;
115+
while (j < n && Character.isDigit(compressed.charAt(j))) {
116+
x = x * 10 + (compressed.charAt(j) - '0');
117+
j++;
118+
}
119+
cnt.merge(c, x, Integer::sum);
120+
i = j;
121+
}
122+
StringBuilder ans = new StringBuilder();
123+
for (var e : cnt.entrySet()) {
124+
ans.append(e.getKey()).append(e.getValue());
125+
}
126+
return ans.toString();
127+
}
128+
}
129+
```
130+
131+
#### C++
132+
133+
```cpp
134+
class Solution {
135+
public:
136+
string betterCompression(string compressed) {
137+
map<char, int> cnt;
138+
int i = 0;
139+
int n = compressed.length();
140+
while (i < n) {
141+
char c = compressed[i];
142+
int j = i + 1;
143+
int x = 0;
144+
while (j < n && isdigit(compressed[j])) {
145+
x = x * 10 + (compressed[j] - '0');
146+
j++;
147+
}
148+
cnt[c] += x;
149+
i = j;
150+
}
151+
stringstream ans;
152+
for (const auto& entry : cnt) {
153+
ans << entry.first << entry.second;
154+
}
155+
return ans.str();
156+
}
157+
};
158+
```
159+
160+
#### Go
161+
162+
```go
163+
func betterCompression(compressed string) string {
164+
cnt := map[byte]int{}
165+
n := len(compressed)
166+
for i := 0; i < n; {
167+
c := compressed[i]
168+
j := i + 1
169+
x := 0
170+
for j < n && compressed[j] >= '0' && compressed[j] <= '9' {
171+
x = x*10 + int(compressed[j]-'0')
172+
j++
173+
}
174+
cnt[c] += x
175+
i = j
176+
}
177+
ans := strings.Builder{}
178+
for c := byte('a'); c <= byte('z'); c++ {
179+
if cnt[c] > 0 {
180+
ans.WriteByte(c)
181+
ans.WriteString(strconv.Itoa(cnt[c]))
182+
}
183+
}
184+
return ans.String()
185+
}
186+
```
187+
188+
#### TypeScript
189+
190+
```ts
191+
function betterCompression(compressed: string): string {
192+
const cnt = new Map<string, number>();
193+
const n = compressed.length;
194+
let i = 0;
195+
196+
while (i < n) {
197+
const c = compressed[i];
198+
let j = i + 1;
199+
let x = 0;
200+
while (j < n && /\d/.test(compressed[j])) {
201+
x = x * 10 + +compressed[j];
202+
j++;
203+
}
204+
cnt.set(c, (cnt.get(c) || 0) + x);
205+
i = j;
206+
}
207+
const keys = Array.from(cnt.keys()).sort();
208+
const ans: string[] = [];
209+
for (const k of keys) {
210+
ans.push(`${k}${cnt.get(k)}`);
211+
}
212+
return ans.join('');
213+
}
214+
```
215+
216+
<!-- tabs:end -->
217+
218+
<!-- solution:end -->
219+
220+
<!-- problem:end -->

0 commit comments

Comments
 (0)