Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lc problem: No.2182 #2211

Merged
merged 1 commit into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: add solutions to lc problem: No.2182
No.2182.Construct String With Repeat Limit
  • Loading branch information
yanglbme committed Jan 13, 2024
commit 4dd2ce6857c0455cf7ded67bec0eede17b07dbcb
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