Skip to content

Commit 6a1d4b6

Browse files
authored
update: 添加问题“1415.长度为n的开心字符串中字典序第k小的字符串”的代码和题解+docs(swapfile) (#1442)
* 1415: WA.cpp (#1441) * 1415: AC.cpp (#1441) - AC,100.00%,91.10% 上个错误反例: last = 'a' can = ['b', 'c'] th = 1 本来应该选can[th] = 'c' 结果can[th] != last就选了'b' * 1415: WA.cpp.dfs (#1441) * 1415: WA.cpp.dfs (#1441) * 1415: AC.cpp.dfs (#1441) - AC,55.51%,54.24% * 1415: AC.cpp.dfs (#1441) - AC,DFS.better,100.00%,55.93% * update: 添加问题“1415.长度为n的开心字符串中字典序第k小的字符串”的代码和题解 (#1442) Signed-off-by: LetMeFly666 <Tisfy@qq.com> --------- Signed-off-by: LetMeFly666 <Tisfy@qq.com>
1 parent 949ac6f commit 6a1d4b6

6 files changed

Lines changed: 700 additions & 0 deletions
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2026-03-14 22:56:17
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2026-03-14 23:33:32
6+
*/
7+
#ifdef _DEBUG
8+
#include "_[1,2]toVector.h"
9+
#endif
10+
11+
class Solution {
12+
private:
13+
int n, k;
14+
string ans;
15+
char can[3] = {'a', 'b', 'c'};
16+
17+
// dfs and return if can stop
18+
bool dfs(string now) {
19+
if (now.size() == n) {
20+
k--;
21+
if (!k) {
22+
ans = now;
23+
return true;
24+
}
25+
return false;
26+
}
27+
28+
char last = now.empty() ? '0' : now.back();
29+
for (int i = 0; i < 3; i++) {
30+
if (can[i] == last) {
31+
continue;
32+
}
33+
if (dfs(now + can[i])) {
34+
return true;
35+
}
36+
}
37+
return false;
38+
}
39+
public:
40+
string getHappyString(int n, int k) {
41+
this->n = n, this->k = k;
42+
dfs("");
43+
return ans;
44+
}
45+
};
46+
47+
#if defined(_WIN32) || defined(__APPLE__)
48+
/*
49+
1 3
50+
51+
c
52+
*/
53+
int main() {
54+
int a, b;
55+
while (cin >> a >> b) {
56+
Solution sol;
57+
cout << sol.getHappyString(a, b) << endl;
58+
}
59+
return 0;
60+
}
61+
#endif
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2026-03-14 22:56:17
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2026-03-14 23:21:37
6+
*/
7+
#ifdef _DEBUG
8+
#include "_[1,2]toVector.h"
9+
#endif
10+
11+
class Solution {
12+
public:
13+
string getHappyString(int n, int k) {
14+
int remain = 1 << (n - 1);
15+
if (k > 3 * remain) {
16+
return "";
17+
}
18+
19+
k--;
20+
char toChoose[3] = {'a', 'b', 'c'};
21+
string ans;
22+
ans.push_back(toChoose[k / remain]);
23+
for (int i = 1; i < n; i++) {
24+
k %= remain;
25+
remain >>= 1;
26+
int th = k / remain;
27+
if (toChoose[th] >= ans.back()) {
28+
th++;
29+
}
30+
ans.push_back(toChoose[th]);
31+
}
32+
return ans;
33+
}
34+
};

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@
582582
|1410.HTML实体解析器|中等|<a href="https://leetcode.cn/problems/html-entity-parser/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/11/23/LeetCode%201410.HTML%E5%AE%9E%E4%BD%93%E8%A7%A3%E6%9E%90%E5%99%A8/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/134571778" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/html-entity-parser/solutions/2538393/letmefly-1410html-shi-ti-jie-xi-qi-zi-fu-psbk/" target="_blank">LeetCode题解</a>|
583583
|1411.给Nx3网格图涂色的方案数|困难|<a href="https://leetcode.cn/problems/number-of-ways-to-paint-n-3-grid" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2026/01/03/LeetCode%201411.%E7%BB%99Nx3%E7%BD%91%E6%A0%BC%E5%9B%BE%E6%B6%82%E8%89%B2%E7%9A%84%E6%96%B9%E6%A1%88%E6%95%B0/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/156545186" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/n-repeated-element-in-size-2n-array/solutions/3872035/letmefly-1411gei-n-x-3-wang-ge-tu-tu-se-gbpc3/" target="_blank">LeetCode题解</a>|
584584
|1413.逐步求和得到正数的最小值|简单|<a href="https://leetcode.cn/problems/minimum-value-to-get-positive-step-by-step-sum/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2022/08/09/LeetCode%201413.%E9%80%90%E6%AD%A5%E6%B1%82%E5%92%8C%E5%BE%97%E5%88%B0%E6%AD%A3%E6%95%B0%E7%9A%84%E6%9C%80%E5%B0%8F%E5%80%BC/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/126241399" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-value-to-get-positive-step-by-step-sum/solution/by-tisfy-txge/" target="_blank">LeetCode题解</a>|
585+
|1415.长度为n的开心字符串中字典序第k小的字符串|中等|<a href="https://leetcode.cn/problems/the-k-th-lexicographical-string-of-all-happy-strings-of-length-n/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2026/03/14/LeetCode%201415.%E9%95%BF%E5%BA%A6%E4%B8%BAn%E7%9A%84%E5%BC%80%E5%BF%83%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E5%AD%97%E5%85%B8%E5%BA%8F%E7%AC%ACk%E5%B0%8F%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/159055459" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/the-k-th-lexicographical-string-of-all-happy-strings-of-length-n/solutions/3925545/letmefly-1415chang-du-wei-n-de-kai-xin-z-ruee/" target="_blank">LeetCode题解</a>|
585586
|1417.重新格式化字符串|简单|<a href="https://leetcode.cn/problems/reformat-the-string/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2022/08/11/LeetCode%201417.%E9%87%8D%E6%96%B0%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/126279589" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/reformat-the-string/solution/letmefly-1417zhong-xin-ge-shi-hua-zi-fu-zhnov/" target="_blank">LeetCode题解</a>|
586587
|1419.数青蛙|中等|<a href="https://leetcode.cn/problems/minimum-number-of-frogs-croaking/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/05/06/LeetCode%201419.%E6%95%B0%E9%9D%92%E8%9B%99/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/130520908" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-number-of-frogs-croaking/solutions/2258226/letmefly-1419shu-qing-wa-by-tisfy-9w23/" target="_blank">LeetCode题解</a>|
587588
|1422.分割字符串的最大得分|简单|<a href="https://leetcode.cn/problems/maximum-score-after-splitting-a-string/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2022/08/14/LeetCode%201422.%E5%88%86%E5%89%B2%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E6%9C%80%E5%A4%A7%E5%BE%97%E5%88%86/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/126329351" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/maximum-score-after-splitting-a-string/solution/letmefly-1422fen-ge-zi-fu-chuan-de-zui-d-8zvi/" target="_blank">LeetCode题解</a>|
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
---
2+
title: 1415.长度为 n 的开心字符串中字典序第 k 小的字符串:DFS构造 / 数学O(1)
3+
date: 2026-03-14 23:31:04
4+
tags: [题解, LeetCode, 中等, 字符串, 回溯, 深度优先搜索, DFS, 模拟, 数学, 构造]
5+
categories: [题解, LeetCode]
6+
---
7+
8+
# 【LetMeFly】1415.长度为 n 的开心字符串中字典序第 k 小的字符串:DFS构造 / 数学O(n)
9+
10+
力扣题目链接:[https://leetcode.cn/problems/the-k-th-lexicographical-string-of-all-happy-strings-of-length-n/](https://leetcode.cn/problems/the-k-th-lexicographical-string-of-all-happy-strings-of-length-n/)
11+
12+
<p>一个 「开心字符串」定义为:</p>
13+
14+
<ul>
15+
<li>仅包含小写字母&nbsp;<code>[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]</code>.</li>
16+
<li>对所有在&nbsp;<code>1</code>&nbsp;到&nbsp;<code>s.length - 1</code>&nbsp;之间的&nbsp;<code>i</code>&nbsp;,满足&nbsp;<code>s[i] != s[i + 1]</code>&nbsp;(字符串的下标从 1 开始)。</li>
17+
</ul>
18+
19+
<p>比方说,字符串&nbsp;<strong>&quot;abc&quot;</strong>,<strong>&quot;ac&quot;&quot;b&quot;</strong> 和&nbsp;<strong>&quot;abcbabcbcb&quot;</strong>&nbsp;都是开心字符串,但是&nbsp;<strong>&quot;aa&quot;</strong>,<strong>&quot;baa&quot;</strong>&nbsp;&nbsp;<strong>&quot;ababbc&quot;</strong>&nbsp;都不是开心字符串。</p>
20+
21+
<p>给你两个整数 <code>n</code>&nbsp;和 <code>k</code>&nbsp;,你需要将长度为 <code>n</code>&nbsp;的所有开心字符串按字典序排序。</p>
22+
23+
<p>请你返回排序后的第 k 个开心字符串,如果长度为 <code>n</code>&nbsp;的开心字符串少于 <code>k</code>&nbsp;个,那么请你返回 <strong>空字符串</strong>&nbsp;。</p>
24+
25+
<p>&nbsp;</p>
26+
27+
<p><strong>示例 1:</strong></p>
28+
29+
<pre><strong>输入:</strong>n = 1, k = 3
30+
<strong>输出:</strong>&quot;c&quot;
31+
<strong>解释:</strong>列表 [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;] 包含了所有长度为 1 的开心字符串。按照字典序排序后第三个字符串为 &quot;c&quot;
32+
</pre>
33+
34+
<p><strong>示例 2:</strong></p>
35+
36+
<pre><strong>输入:</strong>n = 1, k = 4
37+
<strong>输出:</strong>&quot;&quot;
38+
<strong>解释:</strong>长度为 1 的开心字符串只有 3 个。
39+
</pre>
40+
41+
<p><strong>示例 3:</strong></p>
42+
43+
<pre><strong>输入:</strong>n = 3, k = 9
44+
<strong>输出:</strong>&quot;cab&quot;
45+
<strong>解释:</strong>长度为 3 的开心字符串总共有 12 个 [&quot;aba&quot;, &quot;abc&quot;, &quot;aca&quot;, &quot;acb&quot;, &quot;bab&quot;, &quot;bac&quot;, &quot;bca&quot;, &quot;bcb&quot;, &quot;cab&quot;, &quot;cac&quot;, &quot;cba&quot;, &quot;cbc&quot;] 。第 9 个字符串为 &quot;cab&quot;
46+
</pre>
47+
48+
<p><strong>示例 4:</strong></p>
49+
50+
<pre><strong>输入:</strong>n = 2, k = 7
51+
<strong>输出:</strong>&quot;&quot;
52+
</pre>
53+
54+
<p><strong>示例 5:</strong></p>
55+
56+
<pre><strong>输入:</strong>n = 10, k = 100
57+
<strong>输出:</strong>&quot;abacbabacb&quot;
58+
</pre>
59+
60+
<p>&nbsp;</p>
61+
62+
<p><strong>提示:</strong></p>
63+
64+
<ul>
65+
<li><code>1 &lt;= n &lt;= 10</code></li>
66+
<li><code>1 &lt;= k &lt;= 100</code></li>
67+
</ul>
68+
69+
<p>&nbsp;</p>
70+
71+
72+
73+
## 解题方法一:DFS构造
74+
75+
写一个`dfs`函数接收已经构造的字符串并继续构造字符串:
76+
77+
+ 如果之前字符串已经长度为`n`了,就看看这是不是第`k`次长度为`n`。如果是,则说明找到了答案;否则,不继续向后追加字符串,结束这层递归在其他层递归继续寻找答案。
78+
+ 否则,尝试把`abc`中每个和上一个字符(如有)不同的字符拼接到字符串上并递归。
79+
80+
特别的,我们可以控制这个函数的返回值,返回`true`代表已经找到了最终答案,可以不再进行后续递归。
81+
82+
+ 时间复杂度$O(nk)$
83+
+ 空间复杂度$O(n)$
84+
85+
### AC代码
86+
87+
#### C++
88+
89+
```cpp
90+
/*
91+
* @LastEditTime: 2026-03-14 23:29:38
92+
*/
93+
class Solution {
94+
private:
95+
int n, k;
96+
string ans;
97+
char can[3] = {'a', 'b', 'c'};
98+
99+
// dfs and return if can stop
100+
bool dfs(string now) {
101+
if (now.size() == n) {
102+
k--;
103+
if (!k) {
104+
ans = now;
105+
return true;
106+
}
107+
return false;
108+
}
109+
110+
char last = now.empty() ? '0' : now.back();
111+
for (int i = 0; i < 3; i++) {
112+
if (can[i] == last) {
113+
continue;
114+
}
115+
if (dfs(now + can[i])) {
116+
return true;
117+
}
118+
}
119+
return false;
120+
}
121+
public:
122+
string getHappyString(int n, int k) {
123+
this->n = n, this->k = k;
124+
dfs("");
125+
return ans;
126+
}
127+
};
128+
129+
#if defined(_WIN32) || defined(__APPLE__)
130+
/*
131+
1 3
132+
133+
c
134+
*/
135+
int main() {
136+
int a, b;
137+
while (cin >> a >> b) {
138+
Solution sol;
139+
cout << sol.getHappyString(a, b) << endl;
140+
}
141+
return 0;
142+
}
143+
#endif
144+
```
145+
146+
## 解题方法二:数学直接找
147+
148+
长度为$n$的字符串一共有多少种开心字符串呢?
149+
150+
> 第一个字符有$3$种选择,后续每个字符有$2$种选择,共计$3\times2^{n-1}$种。
151+
>
152+
> 如果$k\gt 3\times2^{n-1}$则答案不存在,返回空串。
153+
154+
第$k$个开心字符串的每一位分别应该对应哪个字符呢?很简单,我们只需要计算下这个字符后面字符串有多少种。
155+
156+
举个例子:
157+
158+
+ 假设后面字符串有$2^2$共4种,而当前$k=3\leq 4$,那么当前字符选哪个?当然选能选的字符中第一个就够了;
159+
+ 假设后面字符串有$2^2$共4种,而当前$k=5\lt 4$,那么当前字符选哪个?当然选能选的字符中第二个,因为选第一个的话后面最多$4$种情况,到不了$k=5$。
160+
161+
> PS: 上面的“能选的字符”指的是属于`abc`且和前一个字符不同的字符。
162+
163+
选完这个字符后,令$k$对剩余种类数取模,并更新剩余字符的种类数。
164+
165+
为什么取模呢?
166+
167+
+ 仍然假设后面字符串有$2^2$共4种,而当前$k=5\lt 4$,假设当前可选字符为`ab`,那么相当于当前选`a`时候后面共有$4$个开心字符串,后面选完了当前字符**确定**`b`了,后面还需要$5\%4=1$个开心字符串,使得总开心字符串数是当前$k=5$个。
168+
169+
我们也可以将$k-1$以便后面的取模整除运算。
170+
171+
+ 时间复杂度$O(n)$
172+
+ 空间复杂度$O(n)$
173+
174+
### AC代码
175+
176+
#### C++
177+
178+
```cpp
179+
/*
180+
* @LastEditTime: 2026-03-14 23:21:37
181+
*/
182+
class Solution {
183+
public:
184+
string getHappyString(int n, int k) {
185+
int remain = 1 << (n - 1);
186+
if (k > 3 * remain) {
187+
return "";
188+
}
189+
190+
k--;
191+
char toChoose[3] = {'a', 'b', 'c'};
192+
string ans;
193+
ans.push_back(toChoose[k / remain]);
194+
for (int i = 1; i < n; i++) {
195+
k %= remain;
196+
remain >>= 1;
197+
int th = k / remain;
198+
if (toChoose[th] >= ans.back()) {
199+
th++;
200+
}
201+
ans.push_back(toChoose[th]);
202+
}
203+
return ans;
204+
}
205+
};
206+
```
207+
208+
感觉描述得还不错哈哈。
209+
210+
> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/159055459)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2026/03/14/LeetCode%201415.%E9%95%BF%E5%BA%A6%E4%B8%BAn%E7%9A%84%E5%BC%80%E5%BF%83%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E5%AD%97%E5%85%B8%E5%BA%8F%E7%AC%ACk%E5%B0%8F%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2/)哦~
211+
>
212+
> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode)

Solutions/Other-English-LearningNotes-SomeWords.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,9 @@ categories: [自用]
18721872
|wreath|n. (祭奠)花圈,(圣诞节)花环|
18731873
|||
18741874
|prohibitive|adj. (法令)禁止的,贵得买不起的|
1875+
|||
1876+
|deduct|v. 减去,扣除,演绎|
1877+
|henceforth|adv. 从此之后|
18751878

18761879
+ 这个web要是能设计得可以闭眼(完全不睁眼)键盘控制背单词就好了。
18771880
+ 也许可以加个AI用最近词编故事功能(返回接口中支持标注所使用单词高亮?)

0 commit comments

Comments
 (0)