Skip to content

Commit 75c134b

Browse files
committed
feat: add solutions to lc problem: No.1830
No.1830.Minimum Number of Operations to Make String Sorted
1 parent 79d9d59 commit 75c134b

File tree

6 files changed

+541
-2
lines changed

6 files changed

+541
-2
lines changed

solution/1800-1899/1830.Minimum Number of Operations to Make String Sorted/README.md

Lines changed: 194 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,215 @@
6464

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

67+
**方法一:计数 + 排列组合 + 预处理**
68+
69+
题目中的操作实际上是求当前排列的上一个字典序排列,因此,我们只需要求出比当前排列小的排列的数量,就是答案。
70+
71+
这里我们需要考虑一个问题,给定每一种字母的频率,我们可以构造出多少种不同的排列?
72+
73+
假设总共有 $n$ 个字母,其中字母 $a$ 有 $n_1$ 个,字母 $b$ 有 $n_2$ 个,字母 $c$ 有 $n_3$ 个,那么我们可以构造出 $\frac{n!}{n_1! \times n_2! \times n_3!}$ 种不同的排列。其中 $n=n_1+n_2+n_3$。
74+
75+
我们可以通过预处理的方式,预先计算出所有的阶乘 $f$ 和阶乘的逆元 $g$。其中阶乘的逆元可以通过费马小定理求得。
76+
77+
接下来,我们从左到右遍历字符串 $s$,对于每一个位置 $i$,我们需要求出当前总共有多少个比 $s[i]$ 小的字母,记为 $m$。那么,我们可以构造出 $m \times \frac{(n - i - 1)!}{n_1! \times n_2! \cdots \times n_k!}$ 种不同的排列,其中 $k$ 为字母的种类数,累加到答案中。接下来,我们将 $s[i]$ 的频率减一,继续遍历下一个位置。
78+
79+
遍历完整个字符串后,即可得到答案。注意答案的取模操作。
80+
81+
时间复杂度 $O(n \times k)$,空间复杂度 $O(n)$。其中 $n$ 和 $k$ 分别为字符串的长度和字母的种类数。
82+
6783
<!-- tabs:start -->
6884

6985
### **Python3**
7086

7187
<!-- 这里可写当前语言的特殊实现逻辑 -->
7288

7389
```python
74-
90+
n = 3010
91+
mod = 10**9 + 7
92+
f = [1] + [0] * n
93+
g = [1] + [0] * n
94+
95+
for i in range(1, n):
96+
f[i] = f[i - 1] * i % mod
97+
g[i] = pow(f[i], mod - 2, mod)
98+
99+
100+
class Solution:
101+
def makeStringSorted(self, s: str) -> int:
102+
cnt = Counter(s)
103+
ans, n = 0, len(s)
104+
for i, c in enumerate(s):
105+
m = sum(v for a, v in cnt.items() if a < c)
106+
t = f[n - i - 1] * m
107+
for v in cnt.values():
108+
t = t * g[v] % mod
109+
ans = (ans + t) % mod
110+
cnt[c] -= 1
111+
if cnt[c] == 0:
112+
cnt.pop(c)
113+
return ans
75114
```
76115

77116
### **Java**
78117

79118
<!-- 这里可写当前语言的特殊实现逻辑 -->
80119

81120
```java
121+
class Solution {
122+
private static final int N = 3010;
123+
private static final int MOD = (int) 1e9 + 7;
124+
private static final long[] f = new long[N];
125+
private static final long[] g = new long[N];
126+
127+
static {
128+
f[0] = 1;
129+
g[0] = 1;
130+
for (int i = 1; i < N; ++i) {
131+
f[i] = f[i - 1] * i % MOD;
132+
g[i] = qmi(f[i], MOD - 2);
133+
}
134+
}
135+
136+
public static long qmi(long a, int k) {
137+
long res = 1;
138+
while (k != 0) {
139+
if ((k & 1) == 1) {
140+
res = res * a % MOD;
141+
}
142+
k >>= 1;
143+
a = a * a % MOD;
144+
}
145+
return res;
146+
}
147+
148+
public int makeStringSorted(String s) {
149+
int[] cnt = new int[26];
150+
int n = s.length();
151+
for (int i = 0; i < n; ++i) {
152+
++cnt[s.charAt(i) - 'a'];
153+
}
154+
long ans = 0;
155+
for (int i = 0; i < n; ++i) {
156+
int m = 0;
157+
for (int j = s.charAt(i) - 'a' - 1; j >= 0; --j) {
158+
m += cnt[j];
159+
}
160+
long t = m * f[n - i - 1] % MOD;
161+
for (int v : cnt) {
162+
t = t * g[v] % MOD;
163+
}
164+
--cnt[s.charAt(i) - 'a'];
165+
ans = (ans + t + MOD) % MOD;
166+
}
167+
return (int) ans;
168+
}
169+
}
170+
```
171+
172+
### **C++**
173+
174+
```cpp
175+
const int N = 3010;
176+
const int MOD = 1e9 + 7;
177+
long f[N];
178+
long g[N];
179+
180+
long qmi(long a, int k) {
181+
long res = 1;
182+
while (k != 0) {
183+
if ((k & 1) == 1) {
184+
res = res * a % MOD;
185+
}
186+
k >>= 1;
187+
a = a * a % MOD;
188+
}
189+
return res;
190+
}
191+
192+
int init = []() {
193+
f[0] = g[0] = 1;
194+
for (int i = 1; i < N; ++i) {
195+
f[i] = f[i - 1] * i % MOD;
196+
g[i] = qmi(f[i], MOD - 2);
197+
}
198+
return 0;
199+
}();
200+
201+
202+
class Solution {
203+
public:
204+
int makeStringSorted(string s) {
205+
int cnt[26]{};
206+
for (char& c : s) {
207+
++cnt[c - 'a'];
208+
}
209+
int n = s.size();
210+
long ans = 0;
211+
for (int i = 0; i < n; ++i) {
212+
int m = 0;
213+
for (int j = s[i] - 'a' - 1; ~j; --j) {
214+
m += cnt[j];
215+
}
216+
long t = m * f[n - i - 1] % MOD;
217+
for (int& v : cnt) {
218+
t = t * g[v] % MOD;
219+
}
220+
ans = (ans + t + MOD) % MOD;
221+
--cnt[s[i] - 'a'];
222+
}
223+
return ans;
224+
}
225+
};
226+
```
82227
228+
### **Go**
229+
230+
```go
231+
const n = 3010
232+
const mod = 1e9 + 7
233+
234+
var f = make([]int, n)
235+
var g = make([]int, n)
236+
237+
func qmi(a, k int) int {
238+
res := 1
239+
for k != 0 {
240+
if k&1 == 1 {
241+
res = res * a % mod
242+
}
243+
k >>= 1
244+
a = a * a % mod
245+
}
246+
return res
247+
}
248+
249+
func init() {
250+
f[0], g[0] = 1, 1
251+
for i := 1; i < n; i++ {
252+
f[i] = f[i-1] * i % mod
253+
g[i] = qmi(f[i], mod-2)
254+
}
255+
}
256+
257+
func makeStringSorted(s string) (ans int) {
258+
cnt := [26]int{}
259+
for _, c := range s {
260+
cnt[c-'a']++
261+
}
262+
for i, c := range s {
263+
m := 0
264+
for j := int(c-'a') - 1; j >= 0; j-- {
265+
m += cnt[j]
266+
}
267+
t := m * f[len(s)-i-1] % mod
268+
for _, v := range cnt {
269+
t = t * g[v] % mod
270+
}
271+
ans = (ans + t + mod) % mod
272+
cnt[c-'a']--
273+
}
274+
return
275+
}
83276
```
84277

85278
### **...**

0 commit comments

Comments
 (0)