Skip to content

Commit

Permalink
feat: add solutions to lc problem: No.2182 (#2211)
Browse files Browse the repository at this point in the history
No.2182.Construct String With Repeat Limit
  • Loading branch information
yanglbme authored Jan 13, 2024
1 parent 6815131 commit 9b2c079
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 137 deletions.
106 changes: 73 additions & 33 deletions solution/2100-2199/2182.Construct String With Repeat Limit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@

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

**方法一:贪心 + 双指针**
**方法一:贪心**

我们先用一个长度为 $26$ 的数组 $cnt$ 统计字符串 $s$ 中每个字符出现的次数,然后从大到小枚举字母表的第 $i$ 个字母,每次取出最多 $\min(cnt[i], repeatLimit)$ 个字母 $i$,如果取完后 $cnt[i]$ 还大于 $0$,则继续取字母表中第 $j$ 个字母,其中 $j$ 是最大的满足 $j < i$ 且 $cnt[j] > 0$ 的下标,直到取完所有字母。

时间复杂度 $O(n + |\Sigma|)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 是字符串 $s$ 的长度,而 $\Sigma$ 是字符集,本题中 $|\Sigma| = 26$。

<!-- tabs:start -->

Expand All @@ -66,23 +70,24 @@ class Solution:
def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
cnt = [0] * 26
for c in s:
cnt[ord(c) - ord('a')] += 1
cnt[ord(c) - ord("a")] += 1
ans = []
j = 24
for i in range(25, -1, -1):
j = i - 1
j = min(i - 1, j)
while 1:
for _ in range(min(repeatLimit, cnt[i])):
cnt[i] -= 1
ans.append(chr(ord('a') + i))
x = min(repeatLimit, cnt[i])
cnt[i] -= x
ans.append(ascii_lowercase[i] * x)
if cnt[i] == 0:
break
while j >= 0 and cnt[j] == 0:
j -= 1
if j < 0:
break
cnt[j] -= 1
ans.append(chr(ord('a') + j))
return ''.join(ans)
ans.append(ascii_lowercase[j])
return "".join(ans)
```

### **Java**
Expand All @@ -93,16 +98,16 @@ class Solution:
class Solution {
public String repeatLimitedString(String s, int repeatLimit) {
int[] cnt = new int[26];
for (char c : s.toCharArray()) {
cnt[c - 'a']++;
for (int i = 0; i < s.length(); ++i) {
++cnt[s.charAt(i) - 'a'];
}
StringBuilder ans = new StringBuilder();
for (int i = 25; i >= 0; --i) {
int j = i - 1;
for (int i = 25, j = 24; i >= 0; --i) {
j = Math.min(j, i - 1);
while (true) {
for (int k = Math.min(repeatLimit, cnt[i]); k > 0; --k) {
cnt[i]--;
for (int k = Math.min(cnt[i], repeatLimit); k > 0; --k) {
ans.append((char) ('a' + i));
--cnt[i];
}
if (cnt[i] == 0) {
break;
Expand All @@ -113,8 +118,8 @@ class Solution {
if (j < 0) {
break;
}
cnt[j]--;
ans.append((char) ('a' + j));
--cnt[j];
}
}
return ans.toString();
Expand All @@ -128,21 +133,29 @@ class Solution {
class Solution {
public:
string repeatLimitedString(string s, int repeatLimit) {
vector<int> cnt(26);
for (char& c : s) cnt[c - 'a']++;
int cnt[26]{};
for (char& c : s) {
++cnt[c - 'a'];
}
string ans;
for (int i = 25; ~i; --i) {
int j = i - 1;
while (true) {
for (int i = 25, j = 24; ~i; --i) {
j = min(j, i - 1);
while (1) {
for (int k = min(cnt[i], repeatLimit); k; --k) {
cnt[i]--;
ans.push_back('a' + i);
ans += 'a' + i;
--cnt[i];
}
if (cnt[i] == 0) {
break;
}
while (j >= 0 && cnt[j] == 0) {
--j;
}
if (j < 0) {
break;
}
if (cnt[i] == 0) break;
while (~j && cnt[j] == 0) --j;
if (j < 0) break;
cnt[j]--;
ans.push_back('a' + j);
ans += 'a' + j;
--cnt[j];
}
}
return ans;
Expand All @@ -154,17 +167,17 @@ public:
```go
func repeatLimitedString(s string, repeatLimit int) string {
cnt := make([]int, 26)
cnt := [26]int{}
for _, c := range s {
cnt[c-'a']++
}
var ans []byte
for i := 25; i >= 0; i-- {
j := i - 1
for i, j := 25, 24; i >= 0; i-- {
j = min(j, i-1)
for {
for k := min(cnt[i], repeatLimit); k > 0; k-- {
ans = append(ans, byte(i+'a'))
cnt[i]--
ans = append(ans, 'a'+byte(i))
}
if cnt[i] == 0 {
break
Expand All @@ -175,8 +188,8 @@ func repeatLimitedString(s string, repeatLimit int) string {
if j < 0 {
break
}
ans = append(ans, byte(j+'a'))
cnt[j]--
ans = append(ans, 'a'+byte(j))
}
}
return string(ans)
Expand All @@ -186,7 +199,34 @@ func repeatLimitedString(s string, repeatLimit int) string {
### **TypeScript**

```ts

function repeatLimitedString(s: string, repeatLimit: number): string {
const cnt: number[] = Array(26).fill(0);
for (const c of s) {
cnt[c.charCodeAt(0) - 97]++;
}
const ans: string[] = [];
for (let i = 25, j = 24; ~i; --i) {
j = Math.min(j, i - 1);
while (true) {
for (let k = Math.min(cnt[i], repeatLimit); k; --k) {
ans.push(String.fromCharCode(97 + i));
--cnt[i];
}
if (!cnt[i]) {
break;
}
while (j >= 0 && !cnt[j]) {
--j;
}
if (j < 0) {
break;
}
ans.push(String.fromCharCode(97 + j));
--cnt[j];
}
}
return ans.join('');
}
```

### **...**
Expand Down
129 changes: 102 additions & 27 deletions solution/2100-2199/2182.Construct String With Repeat Limit/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ Note that the string &quot;bbabaaa&quot; is lexicographically larger but the let

## Solutions

**Solution 1: Greedy Algorithm**

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.

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$.

<!-- tabs:start -->

### **Python3**
Expand All @@ -57,23 +63,24 @@ class Solution:
def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
cnt = [0] * 26
for c in s:
cnt[ord(c) - ord('a')] += 1
cnt[ord(c) - ord("a")] += 1
ans = []
j = 24
for i in range(25, -1, -1):
j = i - 1
j = min(i - 1, j)
while 1:
for _ in range(min(repeatLimit, cnt[i])):
cnt[i] -= 1
ans.append(chr(ord('a') + i))
x = min(repeatLimit, cnt[i])
cnt[i] -= x
ans.append(ascii_lowercase[i] * x)
if cnt[i] == 0:
break
while j >= 0 and cnt[j] == 0:
j -= 1
if j < 0:
break
cnt[j] -= 1
ans.append(chr(ord('a') + j))
return ''.join(ans)
ans.append(ascii_lowercase[j])
return "".join(ans)
```

### **Java**
Expand All @@ -82,16 +89,16 @@ class Solution:
class Solution {
public String repeatLimitedString(String s, int repeatLimit) {
int[] cnt = new int[26];
for (char c : s.toCharArray()) {
cnt[c - 'a']++;
for (int i = 0; i < s.length(); ++i) {
++cnt[s.charAt(i) - 'a'];
}
StringBuilder ans = new StringBuilder();
for (int i = 25; i >= 0; --i) {
int j = i - 1;
for (int i = 25, j = 24; i >= 0; --i) {
j = Math.min(j, i - 1);
while (true) {
for (int k = Math.min(repeatLimit, cnt[i]); k > 0; --k) {
cnt[i]--;
for (int k = Math.min(cnt[i], repeatLimit); k > 0; --k) {
ans.append((char) ('a' + i));
--cnt[i];
}
if (cnt[i] == 0) {
break;
Expand All @@ -102,8 +109,8 @@ class Solution {
if (j < 0) {
break;
}
cnt[j]--;
ans.append((char) ('a' + j));
--cnt[j];
}
}
return ans.toString();
Expand All @@ -117,32 +124,100 @@ class Solution {
class Solution {
public:
string repeatLimitedString(string s, int repeatLimit) {
vector<int> cnt(26);
for (char& c : s) cnt[c - 'a']++;
int cnt[26]{};
for (char& c : s) {
++cnt[c - 'a'];
}
string ans;
for (int i = 25; ~i; --i) {
int j = i - 1;
while (true) {
for (int i = 25, j = 24; ~i; --i) {
j = min(j, i - 1);
while (1) {
for (int k = min(cnt[i], repeatLimit); k; --k) {
cnt[i]--;
ans.push_back('a' + i);
ans += 'a' + i;
--cnt[i];
}
if (cnt[i] == 0) {
break;
}
while (j >= 0 && cnt[j] == 0) {
--j;
}
if (j < 0) {
break;
}
if (cnt[i] == 0) break;
while (~j && cnt[j] == 0) --j;
if (j < 0) break;
cnt[j]--;
ans.push_back('a' + j);
ans += 'a' + j;
--cnt[j];
}
}
return ans;
}
};
```
### **Go**
```go
func repeatLimitedString(s string, repeatLimit int) string {
cnt := [26]int{}
for _, c := range s {
cnt[c-'a']++
}
var ans []byte
for i, j := 25, 24; i >= 0; i-- {
j = min(j, i-1)
for {
for k := min(cnt[i], repeatLimit); k > 0; k-- {
ans = append(ans, byte(i+'a'))
cnt[i]--
}
if cnt[i] == 0 {
break
}
for j >= 0 && cnt[j] == 0 {
j--
}
if j < 0 {
break
}
ans = append(ans, byte(j+'a'))
cnt[j]--
}
}
return string(ans)
}
```

### **TypeScript**

```ts
function repeatLimitedString(s: string, repeatLimit: number): string {
const cnt: number[] = Array(26).fill(0);
for (const c of s) {
cnt[c.charCodeAt(0) - 97]++;
}
const ans: string[] = [];
for (let i = 25, j = 24; ~i; --i) {
j = Math.min(j, i - 1);
while (true) {
for (let k = Math.min(cnt[i], repeatLimit); k; --k) {
ans.push(String.fromCharCode(97 + i));
--cnt[i];
}
if (!cnt[i]) {
break;
}
while (j >= 0 && !cnt[j]) {
--j;
}
if (j < 0) {
break;
}
ans.push(String.fromCharCode(97 + j));
--cnt[j];
}
}
return ans.join('');
}
```

### **...**
Expand Down
Loading

0 comments on commit 9b2c079

Please sign in to comment.