最小步数归零问题| 豆包MarsCode AI刷题

43 阅读4分钟

问题描述

小R拿到了一个长度为n的数组,其中每个元素都是一个正整数。小R发现每次可以删除某个数组中某个数的一位数字,这样可以逐步将所有数字变为0。他想知道,要将数组中所有数字都变为0,最少需要多少步?

例如:

  • 对于数字 103,小R可以选择删除第1位数字,将其变为 3;或者删除第2位数字,变为 13,又或者删除第3位数字,将其变为 10。最终目标是将所有数字都删除为0。

思路分析

  1. 问题本质

    • 每次删除一个数字的一位,可以将其变为0。因此,我们需要统计每个数字中非零数字的个数,这个个数就是删除该数字所需的步数。
    • 例如,数字 103 有 2 个非零数字(1 和 3),因此需要 2 步将其变为0。
  2. 解决方案

    • 将每个数字转换为字符串,逐位检查并统计非零数字的个数。
    • 使用一个辅助函数 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 
} 
}

知识总结

  1. 字符串处理

    • 在 Java 中,可以使用 String.valueOf 方法将数字转换为字符串。
    • String.toCharArray 方法可以将字符串转换为字符数组,便于逐位处理。
  2. 字符检查

    • 使用 if (digit != '0') 可以检查字符是否为非零数字。
  3. 数组处理

    • 使用 for 循环遍历数组中的每一个元素。
    • 可以通过 a.length 获取数组的长度。
  4. 性能优化

    • 避免不必要的字符串转换:虽然字符串处理直观,但使用数学方法(如 Math.log10)可以减少字符串转换的开销。
    • 并行流:对于大数组,可以使用 Arrays.stream(a).parallel().map(Main::removeNonZeroDigits).sum() 来加速处理。

个人理解与学习建议

  1. 问题简化

    • 这个问题的核心是如何统计每个数字中非零数字的个数。通过将数字转换为字符串,逐位检查字符是否为非零数字,可以轻松解决这个问题。
  2. 代码可读性

    • 在编写代码时,尽量使用有意义的变量名,如 nonZeroCount 和 digit,这样可以使代码更易读。
    • 添加注释,特别是对于复杂逻辑的部分,可以提高代码的可维护性。
  3. 性能考虑

    • 对于简单的字符串处理,性能开销是可以接受的。但如果处理非常大的数组或非常大的数字,可以考虑使用数学方法来减少字符串转换的开销。
    • 并行流可以在多核处理器上加速数组处理,但需要权衡开销,对于小数组可能不划算。
  4. 学习建议

    • 理解问题本质:在解决编程问题时,首先理解问题的本质,将其简化为可操作的形式。
    • 掌握基本技能:熟练掌握字符串处理、字符检查和数组处理等基本技能,可以在很多问题中派上用场。
    • 编写测试用例:在编写代码时,先思考测试用例,确保代码的正确性和鲁棒性。
    • 优化意识:在代码实现时,考虑性能优化的方法,但不要过度优化,要保持代码的可读性和可维护性。