青训营X豆包MarsCode 19.字典序最小的01字符串 | 豆包MarsCode AI 刷题

130 阅读5分钟

问题描述

小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。

例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过2次操作得到的字典序最小的字符串。

现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。

代码

public class Main {
	public static String solution(int n, int k, String s) {
		// write code here
		char[] str = s.toCharArray();
		// 使用贪心算法,每次选择最小的字符并尽可能向前移动
		for (int i = 0; i < n && k > 0; i++) {
			// 找到当前位置到 i+k 范围内最小的字符
			int minIndex = i;
			for (int j = i + 1; j <= i + k && j < n; j++) {
				if (str[j] < str[minIndex]) {
					minIndex = j;
				}
			}
			// 将最小的字符移动到当前位置
			while (minIndex > i) {
				swapChar(str, minIndex, minIndex - 1);
				minIndex--;
				k--;
			}
		}
		return new String(str);
	}

	public static void swapChar(char[] array, int i, int j) {
		char temp = array[i];
		array[i] = array[j];
		array[j] = temp;
	}

	public static void main(String[] args) {
		System.out.println(solution(5, 2, "01010").equals("00101"));
		System.out.println(solution(7, 3, "1101001").equals("0110101"));
		System.out.println(solution(4, 1, "1001").equals("0101"));
	}
}

代码解析

1.  solution  方法: 首先将输入字符串  s  转换为字符数组  str ,方便后续操作。 外层循环通过  for (int i = 0; i < n && k > 0; i++) ,遍历字符串的前  n  个字符( n  是字符串长度),并且只要还有操作次数  k  就继续循环。 在内层循环  for (int j = i + 1; j <= i + k && j < n; j++)  中,从当前位置  i  的下一个位置开始,到  i + k  位置(但不超过字符串末尾  n )范围内寻找最小的字符,记录其索引  minIndex 。 然后通过  while (minIndex > i)  循环,将找到的最小字符通过不断交换相邻字符的方式移动到当前位置  i ,每次交换减少操作次数  k 。 2.  swapChar  方法: 简单的交换字符数组中两个指定索引位置的字符,用于在移动最小字符时进行相邻字符交换。

知识总结

1. 贪心算法: 代码中使用了贪心算法思想。在每一步操作中,都选择当前位置到  i + k  范围内字典序最小的字符,并将其移动到当前位置,期望通过这样的局部最优选择来达到最终字典序最小的字符串这个全局最优解。这种贪心策略在这个问题中是合理的,因为每次将较小的字符往前移动,能使整体字符串字典序变小的可能性更大。 2. 字符串处理: 涉及到将字符串转换为字符数组以便进行字符级别的操作,以及通过交换字符来改变字符串的构成。 3. 循环与索引操作: 运用多层循环来遍历字符串的不同范围,通过索引准确地定位和操作字符数组中的元素,并且在移动字符时合理地更新索引和操作次数。

学习计划

1. 深入学习贪心算法: 学习更多贪心算法的经典例题,如活动安排问题、背包问题的贪心解法等,理解贪心算法的适用场景和证明方法,能够在遇到类似问题时准确判断是否可以使用贪心算法。 分析贪心算法的时间复杂度和空间复杂度,学习如何优化贪心算法的实现,例如在本题中是否可以通过一些数据结构的辅助来更高效地找到最小字符。 2. 强化字符串处理技巧: 学习字符串的各种常见操作方法,如字符串分割、拼接、替换、查找子串等,掌握不同编程语言中字符串处理库函数的使用。 做一些字符串处理的综合练习题,包括字符串加密解密、字符串模式匹配与替换等,提高对字符串处理的熟练度。 3. 巩固数据结构与算法基础: 复习数组、链表等基础数据结构,理解它们在不同算法中的应用,如本题中字符数组的使用以及如果用链表来表示字符串可能的操作变化。 学习排序算法,因为字符串字典序的比较本质上与排序相关,了解不同排序算法的特点和适用场景,例如本题中寻找最小字符的过程类似于选择排序的局部操作。

工具运用

1. 集成开发环境(IDE): 如 Eclipse、IntelliJ IDEA 等,可以方便地编写、调试代码。在学习过程中,利用 IDE 的代码自动补全、语法检查、调试工具等功能提高开发效率和代码质量。例如,在调试上述代码时,可以设置断点,查看变量值的变化,理解代码执行流程。 2. 代码版本管理工具: 如 Git,可以对代码进行版本管理。在学习算法和编写代码过程中,通过 Git 记录代码的不同版本变化,方便回顾和比较不同阶段的代码,也便于与他人协作学习和分享代码。 3. 在线编程学习平台: 如 LeetCode、牛客网等,这些平台提供了大量的算法练习题,包括字符串处理和贪心算法相关的题目。可以在这些平台上提交代码,查看代码的运行结果和时间、空间复杂度分析,与其他学习者交流解题思路和代码优化方法。