Skip to content

Commit 1f434d6

Browse files
committed
add 227,899
1 parent a4c6a12 commit 1f434d6

File tree

7 files changed

+2472
-1568
lines changed

7 files changed

+2472
-1568
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ node script deploy.sh
6060

6161
## 🔐 Problems & Solutions
6262

63-
完成进度([1064](./TOC-By-ID.md)🔑/ [2726](https://leetcode.cn/problemset/all/)🔒)
63+
完成进度([1066](./TOC-By-ID.md)🔑/ [2727](https://leetcode.cn/problemset/all/)🔒)
6464

6565
- 🔗 [标签查找](./TOC-By-Tag.md)
6666

TOC-By-ID.md

Lines changed: 649 additions & 350 deletions
Large diffs are not rendered by default.

TOC-By-Tag.md

Lines changed: 1317 additions & 1182 deletions
Large diffs are not rendered by default.

algorithms/801-900/899.orderly-queue.md

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# [899.有序队列](https://leetcode.cn/problems/orderly-queue/)
2+
3+
<p>给定一个字符串 <code>s</code> 和一个整数 <code>k</code>&nbsp;。你可以从 <code>s</code> 的前 <code>k</code> 个字母中选择一个,并把它加到字符串的末尾。</p>
4+
5+
<p>返回 <em>在应用上述步骤的任意数量的移动后,字典上最小的字符串&nbsp;</em>。</p>
6+
7+
<p>&nbsp;</p>
8+
9+
<p><strong>示例 1:</strong></p>
10+
11+
<pre>
12+
<strong>输入:</strong>s = "cba", k = 1
13+
<strong>输出:</strong>"acb"
14+
<strong>解释:</strong>
15+
在第一步中,我们将第一个字符(“c”)移动到最后,获得字符串 “bac”。
16+
在第二步中,我们将第一个字符(“b”)移动到最后,获得最终结果 “acb”。
17+
</pre>
18+
19+
<p><strong>示例 2:</strong></p>
20+
21+
<pre>
22+
<strong>输入:</strong>s = "baaca", k = 3
23+
<strong>输出:</strong>"aaabc"
24+
<strong>解释:
25+
</strong>在第一步中,我们将第一个字符(“b”)移动到最后,获得字符串 “aacab”。
26+
在第二步中,我们将第三个字符(“c”)移动到最后,获得最终结果 “aaabc”。
27+
</pre>
28+
29+
<p>&nbsp;</p>
30+
31+
<p><strong>提示:</strong></p>
32+
33+
<ul>
34+
<li><code>1 &lt;= k&nbsp;&lt;= S.length&nbsp;&lt;= 1000</code></li>
35+
<li><code>s</code>&nbsp;只由小写字母组成。</li>
36+
</ul>
37+
38+
39+
<details>
40+
<summary>标签:</summary>
41+
['数学', '字符串', '排序']
42+
</details>
43+
44+
<details>
45+
<summary>难度:Hard</summary>
46+
喜欢:82
47+
</details>
48+
49+
50+
----------
51+
52+
# 字符串的最小表示法
53+
54+
55+
56+
已知字符串 $S=bacacabc$ ,求 $S$ 的最小表示法。
57+
58+
59+
60+
定义 $S[i, j]$ 表示 下标 从 $i$ 到 $j$ 的子串;
61+
62+
定义**同构字符串** $B[i] = S[i,...,n] + S[1,...,i-1]$;
63+
64+
我们使用开二倍空间的方式来处理环形问题。将 $S$ 复制一份 接到尾部 $SS = bacacabcbacacabc$,则 $B[i] = SS[i, i+n-1]$
65+
66+
67+
68+
比较过程:$i=2,j=4, k=3$
69+
70+
当 $SS[i+k] = SS[j+k]$ 时, $k++$;
71+
72+
当 $SS[j+k] < SS[i+k]$ 时,$B[j]$ 为更小的表示法,同样,$\forall_{1<=p<k} B[p]$ 都不为字符串的最小表示法,因为对于 $\forall_{1<=p<k} B[i+p]$ 都存在对应的一个$\forall_{1<=p<k} B[j+p]$ 且 $B[j+p]$ 更小;所以 $i = i+k+1$ ;如果此时 $i=j$,则 $B[i]$和 $B[j]$ 表示同一字符串, 需要将 $i$ 移到下一位,$i++$;
73+
74+
当 $SS[j+k] > SS[i+k]$ 时,处理方法同上;
75+
76+
77+
78+
![image-20220803092243994](https://muyids.oss-cn-beijing.aliyuncs.com/img/image-20220803092243994.png)
79+
80+
81+
82+
## 核心代码实现
83+
84+
85+
86+
```cpp
87+
int n = strlen(s + 1);
88+
for (int i = 1; i <= n; i++) s[n+i] = s[i];
89+
int i = 1, j = 2, k;
90+
while (i <= n && j <= n) {
91+
for (k = 0; k < n && s[i+k] == s[j+k]; k++);
92+
if (k == n) break;
93+
if (s[i+k] > s[j+k]) {
94+
i = i + k + 1;
95+
if (i == j) i++;
96+
} else {
97+
j = j + k + 1;
98+
if (i == j) j++;
99+
}
100+
}
101+
ans = min(i, j);
102+
```
103+
104+
105+
106+
## (分情况讨论) $O(n)$
107+
108+
109+
110+
当k=1时,用字符串的最小表示法求解;
111+
112+
当 k>=2时,可以移动成任意最小字符串;比如edcba,可以转换成abcde,可以自己转换证明;
113+
114+
115+
116+
## 时间复杂度
117+
118+
$O(n)$
119+
120+
## 代码实现
121+
122+
```java []
123+
class Solution {
124+
public String orderlyQueue(String s, int k) {
125+
if (k == 1) {
126+
String res = s;
127+
for (int i = 0; i < s.length(); i++) {
128+
s = s.substring(1) + s.charAt(0);
129+
if (s.compareTo(res) < 0) res = s;
130+
}
131+
return res;
132+
}
133+
char[] ss = s.toCharArray();
134+
Arrays.sort(ss);
135+
return new String(ss);
136+
}
137+
}
138+
```
139+
140+
```cpp []
141+
142+
```
143+
144+
## 参考文献
145+
146+
147+
148+
## 相似题目
149+
150+
151+
152+
### [158. 项链](https://www.acwing.com/problem/content/160/)
153+
154+
155+
156+
判定 两个字符串 $S, T$ 是否**同构**,可以通过比较其 **最小表示法** 是否相等实现
157+
158+
159+
160+
```cpp
161+
#include <iostream>
162+
#include <cstring>
163+
#include <algorithm>
164+
using namespace std;
165+
166+
const int N = 2000010;
167+
char a[N], b[N];
168+
169+
int dict_min(char s[]){
170+
int n = strlen(s + 1);
171+
for (int i = 1; i <= n; i ++ ) s[n+i] = s[i];
172+
int i = 1, j = 2, k;
173+
while (i<=n && j <= n){
174+
for ( k = 0; k < n && s[i+k] == s[j+k]; k ++ );
175+
if (k ==n) break;
176+
if (s[i+k] > s[j+k]) {
177+
i = i+k+1;
178+
if (i==j) i++;
179+
} else {
180+
j = j+k+1;
181+
if (i==j) j++;
182+
}
183+
}
184+
return min(i, j);
185+
}
186+
187+
int main()
188+
{
189+
scanf("%s", a + 1);
190+
int n = strlen(a+1), x = dict_min(a);
191+
scanf("%s", b+1);
192+
int m = strlen(b+1), y = dict_min(b);
193+
a[x + n] = b[y + m] = 0;
194+
if (m ==n && !strcmp(a +x, b+y)) {
195+
cout << "Yes" << endl;
196+
puts(a+x);
197+
}else cout << "No" << endl;
198+
return 0;
199+
}
200+
```
201+
202+
203+

0 commit comments

Comments
 (0)