今天给大家分享题库中较难的一道字典序题目的解题思路笔记
问题描述
小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。
例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过2次操作得到的字典序最小的字符串。
现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。
问题解释
字典序在这里指的是按照字母顺序排列字符串的方式,"0" 比 "1" 小,所以我们想尽可能把 "0" 移到字符串的左侧,使整个字符串看起来更小。小U可以通过交换相邻字符来实现这个目标,且交换次数不超过 k 次。
例如,给定字符串 "01010",并且允许最多进行 2 次相邻字符交换,可以将字符串调整为 "00101"。这是通过不超过 2 次交换可以获得的最小字典序字符串。
这道题的核心思想是将每个 '0' 尽可能向左移动,以获得字典序最小的字符串。通过在有限的 ( k ) 次交换中,把 '0' 和其左侧的 '1' 交换位置,逐步优化字符串的排序。这样的方法能在规定的操作次数内,尽可能接近理想的最小字典序。
代码解析
def solution(n: int, k: int, s: str) -> str:
s = list(s) # 将字符串转换成列表以便于交换操作
for i in range(n):
if s[i] == '0': # 找到每个 '0'
j = i # 开始检查 '0' 可以移动到的最左位置
while j > 0 and s[j - 1] == '1' and k > 0:
# 当左边是 '1' 并且 k > 0 时,交换 '0' 和 '1'
s[j], s[j - 1] = s[j - 1], s[j]
j -= 1 # 继续检查更左的位置
k -= 1 # 每交换一次,操作次数 -1
return "".join(s) # 将列表转换回字符串
if __name__ == '__main__':
print(solution(5, 2, "01010") == '00101') # 期望输出: '00101'
print(solution(7, 3, "1101001") == '0110101') # 期望输出: '0110101'
print(solution(4, 1, "1001") == '0101') # 期望输出: '0101'
代码逻辑
-
字符串转为列表:为了方便字符交换,将输入字符串转换为列表。
-
遍历字符串:从左到右遍历字符串,寻找每个 '0'。
-
移动 '0' :对于每个 '0',尝试将它往左移,只要:
- 左边是 '1'。
- 还有剩余的操作次数 kkk。 每次交换一个 '0' 和其左侧的 '1',并减少 kkk。
-
返回结果:最终将列表转回字符串并返回。
样例分析
-
输入:"01010", k=2
- 初始字符串:"01010"
- 发现第一个 '0',可以进行 2 次操作,把它移动到最左边,得到 "00101"。
- 期望输出:"00101"。
-
输入:"1101001", k=3
- 初始字符串:"1101001"
- 可以将最后一个 '0' 移动两次,将前一个 '0' 移动一次,得到 "0110101"。
- 期望输出:"0110101"。
-
输入:"1001", k=1
- 初始字符串:"1001"
- 只能进行 1 次操作,将第一个 '0' 移动一次,得到 "0101"。
- 期望输出:"0101"。
总的来说,这道题目要求我们在限定的操作次数内,通过交换相邻字符,使字符串的字典序尽可能小。解法的关键在于逐一将每个 '0' 尽量向左移动,优化排序,并在交换次数用完之前尽可能完成更多调整。这种贪心策略在确保每一步操作都朝着优化目标前进的同时,也保证了操作的有效性和效率。