1.题目
2.思路
在有限的移动次数中,尽可能把0往前移
样例1:
输入:n= 5,k= 2,s="01010"
第一次移动 "00110"
第二次移动"00101"
输出::'00101'
问题理解
你需要通过最多 k 次相邻字符交换操作,使得给定的由 0 和 1 组成的字符串 s 的字典序最小。字典序最小意味着字符串中的 0 应该尽可能地排在前面, 1 应该尽可能地排在后面。
数据结构选择
由于我们只需要处理字符串中的字符,并且字符串是不可变的,我们可以使用列表来存储字符串中的字符,以便于进行交换操作。
算法步骤
- 转换字符串为列表:将字符串
s转换为列表s_list,以便于进行交换操作。 - 贪心策略:从左到右遍历字符串,尝试将当前位置的
0尽可能地向左移动,直到达到k次操作的限制。 - 交换操作:在遍历过程中,如果当前字符是
0,尝试将其向左移动,直到遇到另一个0或者达到k次操作的限制。 - 转换回字符串:完成所有操作后,将列表转换回字符串并返回。
3.代码
3.1从左往右遍历,遇到0向左移
def solution(n: int, k: int, s: str) -> str:
# write code here
s_list = list(s)
swap_count = 0
while swap_count < k:
for i in range(n):
# 当前字符为0,且不是第一个
if s[i] == 0 and i != 0:
# 和前一个交换
s[i], s[i - 1] = s[i - 1], s[i]
return str(s_list)
交换一次,swap_count+1,如果没有交换,会进入死循环,所以当for循环执行完,要跳出while循环
def solution(n: int, k: int, s: str) -> str:
# write code here
s_list = list(s)
swap_count = 0
while swap_count < k:
for i in range(n):
# 当前字符为0,且不是第一个
if s[i] == 0 and i != 0:
# 和前一个交换
s[i], s[i - 1] = s[i - 1], s[i]
swap_count += 1
break
return str(s_list)
不应该用while循环在外层控制结束,应在每次swap_count += 1时判断是否结束
def solution(n: int, k: int, s: str) -> str:
# write code here
s_list = list(s)
swap_count = 1
for i in range(n):
# 当前字符为0,且不是第一个
if s[i] == 0 and i != 0:
# 和前一个交换
s[i], s[i - 1] = s[i - 1], s[i]
swap_count += 1
if swap_count >= k:
break
return str(s_list)
- 发现交换的时候忘了用
s_list if s_list[i] == 0 and i != 0:这里应该用's_list[i] == '0'if swap_count >= k:改为if swap_count >= k:- 列表转字符串:
string.join(iterable)
def solution(n: int, k: int, s: str) -> str:
# write code here
s_list = list(s)
swap_count = 1
for i in range(n):
# 当前字符为0,且不是第一个
if s_list[i] == '0' and i != 0:
# 和前一个交换
s_list[i], s_list[i - 1] = s_list[i - 1], s_list[i]
swap_count += 1
if swap_count > k:
break
return "".join(s_list)
print(solution(7, 3, "1101001"))输出结果是1010011,不能一次从左往右遍历,可能有其他情况字典序更小
3.2修改贪心策略
我们每次都选择当前位置及其右侧的最小字符,并将其尽可能地向左移动,直到达到 k 次交换的限制。这样可以确保在有限的交换次数内,得到字典序最小的字符串。
def solution(n: int, k: int, s: str) -> str:
# write code here
s_list = list(s)
swap_count = 0
for i in range(n):
# 找出当前字符后最小的字符
min_index = i
for j in range(i + 1, n):
if s_list[j] < s_list[min_index]:
min_index = j
# 尽可能往前移
while min_index > i and swap_count < k:
s_list[min_index], s_list[min_index - 1] = s_list[min_index - 1], s_list[min_index]
min_index -= 1
swap_count += 1
# 如果达到最大交换次数,break
if swap_count >= k:
break
return "".join(s_list)
if __name__ == '__main__':
print(solution(5, 2, "01010"))
print(solution(7, 3, "1101001"))
print(solution(5, 2, "01010") == '00101')
print(solution(7, 3, "1101001") == '0110101')
print(solution(4, 1, "1001") == '0101')