这个问题的核心在于通过交换相邻字符,使得字符串的字典序最小化。字典序最小化意味着尽可能将 '0' 移到字符串的前面,而将 '1' 移到后面。由于交换操作限制为相邻字符的交换,并且最多只能进行 k 次交换,我们需要设计一个策略,尽量利用有限的交换次数来优化字典序。
问题解析
我们的问题可以简化为:如何通过至多 k 次相邻字符交换,将字符串 s 中的 '0' 尽量移动到左边,'1' 移动到右边,从而获得字典序最小的字符串。
字典序最小的策略
字典序是按字符的顺序来排序的,类似于字母表顺序:
'0'的字典序比'1'小,因此我们希望把'0'尽可能多地移到字符串的左侧,而'1'尽量往右移。
我们可以通过以下方法来优化字典序:
- 从左到右扫描字符串:遍历字符串的每个字符,寻找
'0'和'1'的组合。 - 将
'0'向左移:当遇到一个'0'时,我们尝试将它移动到更左侧。如果'0'和它前面的'1'可以交换,我们就交换它们。每次交换后,k次操作减少 1。 - 限制交换次数:如果
k达到上限,即我们已经用了k次交换,就停止继续交换。
交换策略
- 遇到
'0'时:我们会寻找该'0'前面的位置,看看是否有'1',并交换它们。每次交换会减少一个操作次数。 - 交换的优先级:在可能的情况下,优先将
'0'移动到离它更近的左边位置,直到操作次数耗尽。
解决思路
- 贪心策略:每当我们遇到一个
'0'时,如果前面有'1'且操作次数k还允许,我们就将这个'0'移到尽量靠前的位置。 - 操作次数的控制:每次交换都会消耗一个操作次数
k,当k达到零时,停止交换。
算法步骤
- 将字符串
s转换成列表(因为字符串是不可变的,列表是可变的)。 - 遍历字符串中的每一个字符,找到
'0',然后向左交换直到操作次数k用尽。 - 每交换一次,
k减 1,直到无法再交换或者操作次数用完。 - 返回最终的字符串。
代码实现
def min_lexicographic_string(s, k):
# 转换为列表,方便修改
s = list(s)
n = len(s)
# 遍历字符串的每个字符
for i in range(n):
if k <= 0:
break # 如果操作次数已经用完,退出
# 如果当前字符是 '0',尝试将它向左交换
if s[i] == '0':
# 从当前字符的左边开始,找到第一个 '1' 并交换
for j in range(i - 1, -1, -1):
if s[j] == '1': # 找到第一个 '1'
s[j], s[j + 1] = s[j + 1], s[j] # 交换
k -= 1 # 减少操作次数
if k == 0: # 如果操作次数用尽,结束
break
else:
break # 如果前面没有 '1',就停止
return ''.join(s) # 将列表转换回字符串
# 示例
s = "01010"
k = 2
result = min_lexicographic_string(s, k)
print(result) # 输出:00110
代码解释
- 转换为列表:我们将输入的字符串
s转换为列表,因为在 Python 中字符串是不可变的,而我们需要修改字符串的内容。 - 遍历字符串:我们通过遍历字符串的每个字符,当遇到
'0'时,尝试将其交换到左边,直到操作次数用尽或者字符串结束。 - 交换操作:如果当前字符是
'0',我们检查它前面的字符,找到第一个'1'后交换它们,并减少操作次数k。 - 操作次数控制:一旦
k达到 0,我们就停止交换,返回当前的字符串。
示例分析
假设输入字符串是 "01010",最多可以进行 2 次交换:
- 初始字符串为
"01010",我们从左到右遍历。 - 第一个
'0'在索引 0,没有前面的'1',不需要交换。 - 第二个
'0'在索引 2,它前面有'1',我们交换它和索引 1 处的'1',此时剩余的操作次数k = 1,字符串变为"00110". - 第三个
'0'在索引 4,我们将它交换到索引 3,剩余的操作次数k = 0,停止交换。
最终得到的字符串是 "00110",这是字典序最小的字符串。
知识总结
建议同学们不必追求数量,要追求质量,找出自己不会的知识点。