Skip to content

Commit 9b2c079

Browse files
authored
feat: add solutions to lc problem: No.2182 (doocs#2211)
No.2182.Construct String With Repeat Limit
1 parent 6815131 commit 9b2c079

File tree

7 files changed

+289
-137
lines changed

7 files changed

+289
-137
lines changed

solution/2100-2199/2182.Construct String With Repeat Limit/README.md

+73-33
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@
5353

5454
<!-- 这里可写通用的实现逻辑 -->
5555

56-
**方法一:贪心 + 双指针**
56+
**方法一:贪心**
57+
58+
我们先用一个长度为 $26$ 的数组 $cnt$ 统计字符串 $s$ 中每个字符出现的次数,然后从大到小枚举字母表的第 $i$ 个字母,每次取出最多 $\min(cnt[i], repeatLimit)$ 个字母 $i$,如果取完后 $cnt[i]$ 还大于 $0$,则继续取字母表中第 $j$ 个字母,其中 $j$ 是最大的满足 $j < i$ 且 $cnt[j] > 0$ 的下标,直到取完所有字母。
59+
60+
时间复杂度 $O(n + |\Sigma|)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 是字符串 $s$ 的长度,而 $\Sigma$ 是字符集,本题中 $|\Sigma| = 26$。
5761

5862
<!-- tabs:start -->
5963

@@ -66,23 +70,24 @@ class Solution:
6670
def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
6771
cnt = [0] * 26
6872
for c in s:
69-
cnt[ord(c) - ord('a')] += 1
73+
cnt[ord(c) - ord("a")] += 1
7074
ans = []
75+
j = 24
7176
for i in range(25, -1, -1):
72-
j = i - 1
77+
j = min(i - 1, j)
7378
while 1:
74-
for _ in range(min(repeatLimit, cnt[i])):
75-
cnt[i] -= 1
76-
ans.append(chr(ord('a') + i))
79+
x = min(repeatLimit, cnt[i])
80+
cnt[i] -= x
81+
ans.append(ascii_lowercase[i] * x)
7782
if cnt[i] == 0:
7883
break
7984
while j >= 0 and cnt[j] == 0:
8085
j -= 1
8186
if j < 0:
8287
break
8388
cnt[j] -= 1
84-
ans.append(chr(ord('a') + j))
85-
return ''.join(ans)
89+
ans.append(ascii_lowercase[j])
90+
return "".join(ans)
8691
```
8792

8893
### **Java**
@@ -93,16 +98,16 @@ class Solution:
9398
class Solution {
9499
public String repeatLimitedString(String s, int repeatLimit) {
95100
int[] cnt = new int[26];
96-
for (char c : s.toCharArray()) {
97-
cnt[c - 'a']++;
101+
for (int i = 0; i < s.length(); ++i) {
102+
++cnt[s.charAt(i) - 'a'];
98103
}
99104
StringBuilder ans = new StringBuilder();
100-
for (int i = 25; i >= 0; --i) {
101-
int j = i - 1;
105+
for (int i = 25, j = 24; i >= 0; --i) {
106+
j = Math.min(j, i - 1);
102107
while (true) {
103-
for (int k = Math.min(repeatLimit, cnt[i]); k > 0; --k) {
104-
cnt[i]--;
108+
for (int k = Math.min(cnt[i], repeatLimit); k > 0; --k) {
105109
ans.append((char) ('a' + i));
110+
--cnt[i];
106111
}
107112
if (cnt[i] == 0) {
108113
break;
@@ -113,8 +118,8 @@ class Solution {
113118
if (j < 0) {
114119
break;
115120
}
116-
cnt[j]--;
117121
ans.append((char) ('a' + j));
122+
--cnt[j];
118123
}
119124
}
120125
return ans.toString();
@@ -128,21 +133,29 @@ class Solution {
128133
class Solution {
129134
public:
130135
string repeatLimitedString(string s, int repeatLimit) {
131-
vector<int> cnt(26);
132-
for (char& c : s) cnt[c - 'a']++;
136+
int cnt[26]{};
137+
for (char& c : s) {
138+
++cnt[c - 'a'];
139+
}
133140
string ans;
134-
for (int i = 25; ~i; --i) {
135-
int j = i - 1;
136-
while (true) {
141+
for (int i = 25, j = 24; ~i; --i) {
142+
j = min(j, i - 1);
143+
while (1) {
137144
for (int k = min(cnt[i], repeatLimit); k; --k) {
138-
cnt[i]--;
139-
ans.push_back('a' + i);
145+
ans += 'a' + i;
146+
--cnt[i];
147+
}
148+
if (cnt[i] == 0) {
149+
break;
150+
}
151+
while (j >= 0 && cnt[j] == 0) {
152+
--j;
153+
}
154+
if (j < 0) {
155+
break;
140156
}
141-
if (cnt[i] == 0) break;
142-
while (~j && cnt[j] == 0) --j;
143-
if (j < 0) break;
144-
cnt[j]--;
145-
ans.push_back('a' + j);
157+
ans += 'a' + j;
158+
--cnt[j];
146159
}
147160
}
148161
return ans;
@@ -154,17 +167,17 @@ public:
154167
155168
```go
156169
func repeatLimitedString(s string, repeatLimit int) string {
157-
cnt := make([]int, 26)
170+
cnt := [26]int{}
158171
for _, c := range s {
159172
cnt[c-'a']++
160173
}
161174
var ans []byte
162-
for i := 25; i >= 0; i-- {
163-
j := i - 1
175+
for i, j := 25, 24; i >= 0; i-- {
176+
j = min(j, i-1)
164177
for {
165178
for k := min(cnt[i], repeatLimit); k > 0; k-- {
179+
ans = append(ans, byte(i+'a'))
166180
cnt[i]--
167-
ans = append(ans, 'a'+byte(i))
168181
}
169182
if cnt[i] == 0 {
170183
break
@@ -175,8 +188,8 @@ func repeatLimitedString(s string, repeatLimit int) string {
175188
if j < 0 {
176189
break
177190
}
191+
ans = append(ans, byte(j+'a'))
178192
cnt[j]--
179-
ans = append(ans, 'a'+byte(j))
180193
}
181194
}
182195
return string(ans)
@@ -186,7 +199,34 @@ func repeatLimitedString(s string, repeatLimit int) string {
186199
### **TypeScript**
187200

188201
```ts
189-
202+
function repeatLimitedString(s: string, repeatLimit: number): string {
203+
const cnt: number[] = Array(26).fill(0);
204+
for (const c of s) {
205+
cnt[c.charCodeAt(0) - 97]++;
206+
}
207+
const ans: string[] = [];
208+
for (let i = 25, j = 24; ~i; --i) {
209+
j = Math.min(j, i - 1);
210+
while (true) {
211+
for (let k = Math.min(cnt[i], repeatLimit); k; --k) {
212+
ans.push(String.fromCharCode(97 + i));
213+
--cnt[i];
214+
}
215+
if (!cnt[i]) {
216+
break;
217+
}
218+
while (j >= 0 && !cnt[j]) {
219+
--j;
220+
}
221+
if (j < 0) {
222+
break;
223+
}
224+
ans.push(String.fromCharCode(97 + j));
225+
--cnt[j];
226+
}
227+
}
228+
return ans.join('');
229+
}
190230
```
191231

192232
### **...**

solution/2100-2199/2182.Construct String With Repeat Limit/README_EN.md

+102-27
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ Note that the string &quot;bbabaaa&quot; is lexicographically larger but the let
4848

4949
## Solutions
5050

51+
**Solution 1: Greedy Algorithm**
52+
53+
First, we use an array $cnt$ of length $26$ to count the number of occurrences of each character in string $s$. Then, we enumerate the $i$th letter of the alphabet in descending order, each time taking out at most $\min(cnt[i], repeatLimit)$ of letter $i$. If after taking them out $cnt[i]$ is still greater than $0$, we continue to take the $j$th letter of the alphabet, where $j$ is the largest index satisfying $j < i$ and $cnt[j] > 0$, until all letters are taken.
54+
55+
The time complexity is $O(n + |\Sigma|)$, and the space complexity is $O(|\Sigma|)$. Here, $n$ is the length of string $s$, and $\Sigma$ is the character set. In this problem, $|\Sigma| = 26$.
56+
5157
<!-- tabs:start -->
5258

5359
### **Python3**
@@ -57,23 +63,24 @@ class Solution:
5763
def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
5864
cnt = [0] * 26
5965
for c in s:
60-
cnt[ord(c) - ord('a')] += 1
66+
cnt[ord(c) - ord("a")] += 1
6167
ans = []
68+
j = 24
6269
for i in range(25, -1, -1):
63-
j = i - 1
70+
j = min(i - 1, j)
6471
while 1:
65-
for _ in range(min(repeatLimit, cnt[i])):
66-
cnt[i] -= 1
67-
ans.append(chr(ord('a') + i))
72+
x = min(repeatLimit, cnt[i])
73+
cnt[i] -= x
74+
ans.append(ascii_lowercase[i] * x)
6875
if cnt[i] == 0:
6976
break
7077
while j >= 0 and cnt[j] == 0:
7178
j -= 1
7279
if j < 0:
7380
break
7481
cnt[j] -= 1
75-
ans.append(chr(ord('a') + j))
76-
return ''.join(ans)
82+
ans.append(ascii_lowercase[j])
83+
return "".join(ans)
7784
```
7885

7986
### **Java**
@@ -82,16 +89,16 @@ class Solution:
8289
class Solution {
8390
public String repeatLimitedString(String s, int repeatLimit) {
8491
int[] cnt = new int[26];
85-
for (char c : s.toCharArray()) {
86-
cnt[c - 'a']++;
92+
for (int i = 0; i < s.length(); ++i) {
93+
++cnt[s.charAt(i) - 'a'];
8794
}
8895
StringBuilder ans = new StringBuilder();
89-
for (int i = 25; i >= 0; --i) {
90-
int j = i - 1;
96+
for (int i = 25, j = 24; i >= 0; --i) {
97+
j = Math.min(j, i - 1);
9198
while (true) {
92-
for (int k = Math.min(repeatLimit, cnt[i]); k > 0; --k) {
93-
cnt[i]--;
99+
for (int k = Math.min(cnt[i], repeatLimit); k > 0; --k) {
94100
ans.append((char) ('a' + i));
101+
--cnt[i];
95102
}
96103
if (cnt[i] == 0) {
97104
break;
@@ -102,8 +109,8 @@ class Solution {
102109
if (j < 0) {
103110
break;
104111
}
105-
cnt[j]--;
106112
ans.append((char) ('a' + j));
113+
--cnt[j];
107114
}
108115
}
109116
return ans.toString();
@@ -117,32 +124,100 @@ class Solution {
117124
class Solution {
118125
public:
119126
string repeatLimitedString(string s, int repeatLimit) {
120-
vector<int> cnt(26);
121-
for (char& c : s) cnt[c - 'a']++;
127+
int cnt[26]{};
128+
for (char& c : s) {
129+
++cnt[c - 'a'];
130+
}
122131
string ans;
123-
for (int i = 25; ~i; --i) {
124-
int j = i - 1;
125-
while (true) {
132+
for (int i = 25, j = 24; ~i; --i) {
133+
j = min(j, i - 1);
134+
while (1) {
126135
for (int k = min(cnt[i], repeatLimit); k; --k) {
127-
cnt[i]--;
128-
ans.push_back('a' + i);
136+
ans += 'a' + i;
137+
--cnt[i];
138+
}
139+
if (cnt[i] == 0) {
140+
break;
141+
}
142+
while (j >= 0 && cnt[j] == 0) {
143+
--j;
144+
}
145+
if (j < 0) {
146+
break;
129147
}
130-
if (cnt[i] == 0) break;
131-
while (~j && cnt[j] == 0) --j;
132-
if (j < 0) break;
133-
cnt[j]--;
134-
ans.push_back('a' + j);
148+
ans += 'a' + j;
149+
--cnt[j];
135150
}
136151
}
137152
return ans;
138153
}
139154
};
140155
```
141156
157+
### **Go**
158+
159+
```go
160+
func repeatLimitedString(s string, repeatLimit int) string {
161+
cnt := [26]int{}
162+
for _, c := range s {
163+
cnt[c-'a']++
164+
}
165+
var ans []byte
166+
for i, j := 25, 24; i >= 0; i-- {
167+
j = min(j, i-1)
168+
for {
169+
for k := min(cnt[i], repeatLimit); k > 0; k-- {
170+
ans = append(ans, byte(i+'a'))
171+
cnt[i]--
172+
}
173+
if cnt[i] == 0 {
174+
break
175+
}
176+
for j >= 0 && cnt[j] == 0 {
177+
j--
178+
}
179+
if j < 0 {
180+
break
181+
}
182+
ans = append(ans, byte(j+'a'))
183+
cnt[j]--
184+
}
185+
}
186+
return string(ans)
187+
}
188+
```
189+
142190
### **TypeScript**
143191

144192
```ts
145-
193+
function repeatLimitedString(s: string, repeatLimit: number): string {
194+
const cnt: number[] = Array(26).fill(0);
195+
for (const c of s) {
196+
cnt[c.charCodeAt(0) - 97]++;
197+
}
198+
const ans: string[] = [];
199+
for (let i = 25, j = 24; ~i; --i) {
200+
j = Math.min(j, i - 1);
201+
while (true) {
202+
for (let k = Math.min(cnt[i], repeatLimit); k; --k) {
203+
ans.push(String.fromCharCode(97 + i));
204+
--cnt[i];
205+
}
206+
if (!cnt[i]) {
207+
break;
208+
}
209+
while (j >= 0 && !cnt[j]) {
210+
--j;
211+
}
212+
if (j < 0) {
213+
break;
214+
}
215+
ans.push(String.fromCharCode(97 + j));
216+
--cnt[j];
217+
}
218+
}
219+
return ans.join('');
220+
}
146221
```
147222

148223
### **...**

0 commit comments

Comments
 (0)