45. 最少步数归零问题

56 阅读2分钟

题目分析

我们的问题是将一个数组中的所有正整数变为0,最小化删除数字所需的步数。每次操作允许删除一个数的任意一位。


解题思路

  1. 删除数字的本质

    • 每个数字有 ( \text{len}(num) ) 个字符,将其逐步删除为 0 的过程需要 ( \text{len}(num) ) 步。
    • 对于一个数组中的所有数字,总步数就是所有数字的位数之和。
  2. 如何计算最小步数

    • 遍历数组中的每个数字,将其转换为字符串,计算字符串的长度,累加到总步数中。
  3. 优化点

    • 数字的位数可通过对每个数字直接使用字符串长度 ( \text{len}(num) ),无需逐位操作。
  4. 算法复杂度

    • 时间复杂度:( O(n \cdot k) ),其中 ( n ) 是数组长度,( k ) 是数字的平均位数。
    • 空间复杂度:( O(1) ),只需记录总步数的变量。

代码实现

以下是 C++ 实现:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

// 求解最少步数
int solution(int n, vector<int>& a) {
    int total_steps = 0; // 总步数
    
    // 遍历数组中的每个数字
    for (int num : a) {
        // 将数字转为字符串,并累加位数
        string num_str = to_string(num);
        total_steps += num_str.size(); // 每位都需要一步删除
    }
    
    return total_steps;
}

int main() {
    // 测试用例
    vector<int> a1 = {10, 13, 22, 100, 30};
    cout << solution(5, a1) << endl; // 输出:7

    vector<int> a2 = {5, 50, 505};
    cout << solution(3, a2) << endl; // 输出:4

    vector<int> a3 = {1000, 1, 10, 100};
    cout << solution(4, a3) << endl; // 输出:4

    return 0;
}

代码解析

  1. 核心逻辑

    • 使用 to_string(num) 将数字转为字符串,获取字符串的长度(即数字的位数)。
    • 每个数字的位数累加到总步数中。
  2. 关键点

    • 数字转换为字符串可以直接获取位数,而不需要逐位操作或除法。
    • 总步数是简单的累加过程,无需复杂的条件判断。

测试结果

示例 1

  • 输入:( n = 5, a = [10, 13, 22, 100, 30] )
  • 解析:
    • 10 → 2 位
    • 13 → 2 位
    • 22 → 2 位
    • 100 → 3 位
    • 30 → 2 位
    • 总步数:( 2 + 2 + 2 + 3 + 2 = 7 )
  • 输出:7

示例 2

  • 输入:( n = 3, a = [5, 50, 505] )
  • 解析:
    • 5 → 1 位
    • 50 → 2 位
    • 505 → 3 位
    • 总步数:( 1 + 2 + 3 = 4 )
  • 输出:4

示例 3

  • 输入:( n = 4, a = [1000, 1, 10, 100] )
  • 解析:
    • 1000 → 4 位
    • 1 → 1 位
    • 10 → 2 位
    • 100 → 3 位
    • 总步数:( 4 + 1 + 2 + 3 = 10 )
  • 输出:10

总结

  1. 方法概述

    • 遍历数组,逐个统计数字的位数并累加。
    • 时间复杂度低,易于实现。
  2. 应用场景

    • 适用于需要统计或操作数字字符数的问题。
  3. 优化潜力

    • 数字位数可以直接通过数学计算 ( \text{floor}(\log_{10}(\text{num}) + 1) ) 获取,避免字符串转换。