1 题目描述
题目:字典序最小的01字符串
小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。
例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过2次操作得到的字典序最小的字符串。
现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。
测试样例
样例1:
输入:
n = 5, k = 2, s = "01010"
输出:'00101'
样例2:
输入:
n = 7, k = 3, s = "1101001"
输出:'0110101'
样例3:
输入:
n = 4, k = 1, s = "1001"
输出:'0101'
2. 分析
要通过有限的移动次数让字符串的字典序最小,即让前面的1尽可能靠后,当然,如果前面有两个连续的1,第一个1和后面的1交换大小不变,但消耗了一次交换次数,这时应该接着往下再判断;
为什么是移动前面的1?在前后都能移动的情况下,移动前面的1可以让字符串的字典序更小,即int(字符串)更小;
3. 解题思路
- 外面一个循环,表示移动次数
k; - 循环里面每次遍历字符串的前
len(s)-1的子字符串(因为要比较下一位是不是0,所以最后得留出来一位),判断是否满足上面分析的条件,如果满足,交换并修改字符串,break循环,表示这次交换已经完成,不需要再判断后面的数字是否满足条件; - 最后返回修改后的字符串;
4. 代码实现
def solution(n: int, k: int, s: str) -> str:
# write code here
for _ in range(k):
for i,c in enumerate(s[:-1]):
if c=='1' and s[i+1]=='0':
# 拼接新字符串,前面和后面的不变,中间的变成'01'
s=s[:i]+'01'+s[i+2:]
break
return s
5. MarsCode AI的思路
-
遍历字符串:从左到右遍历字符串,记录当前已经使用的交换次数。
-
交换操作:
- 如果当前字符是
1,并且后面有0,尝试将这个0与前面的1交换。 - 每次交换后,更新字符串和剩余的交换次数。
- 如果当前字符是
-
终止条件:当达到
k次交换操作或者字符串遍历结束时,停止操作。
def solution(n: int, k: int, s: str) -> str:
# 将字符串转换为列表以便于操作
s = list(s)
# 遍历字符串
for i in range(n):
if k == 0:
break
if s[i] == '1':
# 查找后面的 '0'
for j in range(i+1, n):
if s[j] == '0':
# 计算需要交换的次数
swaps_needed = j - i
if swaps_needed <= k:
# 执行交换
s[i], s[j] = s[j], s[i]
k -= swaps_needed
break
# 将列表转换回字符串
return ''.join(s)
- 看起来是从左往右遍历字符串,把遇到第一个1和它右边的第一个0进行交换,计算交换次数,从
k中减掉这个交换次数表示消耗掉了,然后从上一步遇到1的右边继续遍历。直到交换次数被消耗为0,也是一种办法,不过似乎略显麻烦;
6. 总结
本题主要思路是弄清楚怎么移动才能让字符串的字典序最小,然后就是在有限移动次数的条件下进行判断。
在刷题过程中利用好AI工具,比如:
- 在没有思路的时候可以让AI尝试给点思路;
- 或者有个api忘了也可以问问;
- 代码审查,让AI检查代码中的潜在错误、警告和改进点,包括性能优化、时空复杂度分析、代码风格和最佳实践等;
AI也会犯错,可以把AI的思路、答案作为参考或建议,在此基础上试着去理解和应用。有时还需要进一步引导,找到最终的最优题解。