问题描述
小R拿到了一个长度为n的数组,其中每个元素都是一个正整数。小R发现每次可以删除某个数组中某个数的一位数字,这样可以逐步将所有数字变为0。他想知道,要将数组中所有数字都变为0,最少需要多少步?
例如:
- 对于数字 103,小R可以选择删除第1位数字,将其变为 3;或者删除第2位数字,变为 13,又或者删除第3位数字,将其变为 10。最终目标是将所有数字都删除为0。
思路分析
-
问题本质:
- 每次删除一个数字的一位,可以将其变为0。因此,我们需要统计每个数字中非零数字的个数,这个个数就是删除该数字所需的步数。
- 例如,数字 103 有 2 个非零数字(1 和 3),因此需要 2 步将其变为0。
-
解决方案:
- 将每个数字转换为字符串,逐位检查并统计非零数字的个数。
- 使用一个辅助函数
removeNonZeroDigits来处理每个数字。 - 在主函数
solution中遍历数组,调用辅助函数并累加结果。
代码详解
public class Main {
public static int solution(int n, int[] a) {
// 初始化结果变量,用于记录总的步数
int result = 0; // 遍历数组中的每一个数字
for (int i = 0; i < a.length; i++) {
// 调用辅助函数,计算将当前数字变为0所需的步数
result += removeNonZeroDigits(a[i]);
} // 返回总的步数
return result;
}
public static int removeNonZeroDigits(int number) {
// 将数字转换为字符串,便于逐位处理
String numberStr = String.valueOf(number); // 初始化计数器,用于记录非零数字的个数
int nonZeroCount = 0; // 逐位检查字符串中的每一个字符
for (char digit : numberStr.toCharArray()) {
// 如果字符不是 '0',则计数器增加1
if (digit != '0') {
nonZeroCount++;
}
} // 返回非零数字的个数,即删除该数字所需的步数
return nonZeroCount;
}
public static void main(String[] args) {
// 测试用例
System.out.println(solution(5, new int[]{10, 13, 22, 100, 30})); // 输出 7
System.out.println(solution(5, new int[]{10, 13, 22, 100, 30}) == 7); // 输出 true System.out.println(solution(3, new int[]{5, 50, 505}) == 4); // 输出 true System.out.println(solution(4, new int[]{1000, 1, 10, 100}) == 4); // 输出 true
}
}
知识总结
-
字符串处理:
- 在 Java 中,可以使用
String.valueOf方法将数字转换为字符串。 String.toCharArray方法可以将字符串转换为字符数组,便于逐位处理。
- 在 Java 中,可以使用
-
字符检查:
- 使用
if (digit != '0')可以检查字符是否为非零数字。
- 使用
-
数组处理:
- 使用
for循环遍历数组中的每一个元素。 - 可以通过
a.length获取数组的长度。
- 使用
-
性能优化:
- 避免不必要的字符串转换:虽然字符串处理直观,但使用数学方法(如
Math.log10)可以减少字符串转换的开销。 - 并行流:对于大数组,可以使用
Arrays.stream(a).parallel().map(Main::removeNonZeroDigits).sum()来加速处理。
- 避免不必要的字符串转换:虽然字符串处理直观,但使用数学方法(如
个人理解与学习建议
-
问题简化:
- 这个问题的核心是如何统计每个数字中非零数字的个数。通过将数字转换为字符串,逐位检查字符是否为非零数字,可以轻松解决这个问题。
-
代码可读性:
- 在编写代码时,尽量使用有意义的变量名,如
nonZeroCount和digit,这样可以使代码更易读。 - 添加注释,特别是对于复杂逻辑的部分,可以提高代码的可维护性。
- 在编写代码时,尽量使用有意义的变量名,如
-
性能考虑:
- 对于简单的字符串处理,性能开销是可以接受的。但如果处理非常大的数组或非常大的数字,可以考虑使用数学方法来减少字符串转换的开销。
- 并行流可以在多核处理器上加速数组处理,但需要权衡开销,对于小数组可能不划算。
-
学习建议:
- 理解问题本质:在解决编程问题时,首先理解问题的本质,将其简化为可操作的形式。
- 掌握基本技能:熟练掌握字符串处理、字符检查和数组处理等基本技能,可以在很多问题中派上用场。
- 编写测试用例:在编写代码时,先思考测试用例,确保代码的正确性和鲁棒性。
- 优化意识:在代码实现时,考虑性能优化的方法,但不要过度优化,要保持代码的可读性和可维护性。