问题描述
小R拿到了一个长度为n的数组,其中每个元素都是一个正整数。小R发现每次可以删除某个数组中某个数的一位数字,这样可以逐步将所有数字变为0。他想知道,要将数组中所有数字都变为0,最少需要多少步?
例如:对于数字 103
,小R可以选择删除第1位数字,将其变为 3
;或者删除第2位数字,变为 13
,又或者删除第3位数字,将其变为 10
。最终目标是将所有数字都删除为0。
测试样例
样例1:
输入:
n = 5,a = [10, 13, 22, 100, 30]
输出:7
样例2:
输入:
n = 3,a = [5, 50, 505]
输出:4
样例3:
输入:
n = 4,a = [1000, 1, 10, 100]
输出:4
思路分析
观察题目发现计算数组中将所有数字变为0的最小步数,只需要遍历数组将数组中每个数字分别变为0,再将步数的和相加就可以计算出结果了。对于每个单独的数字将它变为0只需要从该数字的最高位到各位遍历,只要某一位的数字不是0,就可以将其删除,这样我们只需要一个计数器来计算需要的步数,那如何从一个数字的最高位到最低位进行遍历呢?只需要将这个数字转换成一个字符串,这样就可以进行遍历了。
代码
#include <string.h>
int solution(int n, int* a) {
int totalSteps = 0;
for (int i = 0; i < n; i++) {
// 将数字转换为字符串
char str[20]; // 假设数字最大长度为20位
sprintf(str, "%d", a[i]);
for(int j=0;j<strlen(str);j++){
if(str[j]!='0') totalSteps++;
}
}
return totalSteps;
}
int main() {
int a1[] = {10, 13, 22, 100, 30};
printf("%d\n", solution(5, a1) == 7);
int a2[] = {5, 50, 505};
printf("%d\n", solution(3, a2) == 4);
int a3[] = {1000, 1, 10, 100};
printf("%d\n", solution(4, a3) == 4);
return 0;
}
代码解析
solution
函数
-
参数:
n
:表示输入数组a
的长度,用于控制循环遍历数组的次数。a
:是一个指向整数数组的指针,指向要进行处理的整数数组。
-
局部变量:
totalSteps
:用于累加将数组中每个数字变为 0 所需删除的位数总和,初始化为 0。
-
循环遍历数组:
- 通过
for
循环for (int i = 0; i < n; i++)
遍历输入数组a
中的每个元素。
- 通过
-
将整数转换为字符串:
- 在每次循环中,对于数组元素
a[i]
,首先定义一个字符数组str
,长度假设为 20 位(这里假设数字最大长度为 20 位,实际应用中可能需要根据具体情况调整),然后使用sprintf
函数将整数a[i]
按照十进制格式转换为字符串并存入str
中。这样就可以通过遍历字符串来分析数字的每一位。
- 在每次循环中,对于数组元素
-
统计非零字符个数:
- 通过内层的
for
循环for(int j=0;j<strlen(str);j++)
遍历刚刚转换得到的字符串str
。在循环中,使用条件判断if(str[j]!='0')
来检查字符串中的每一位字符,如果字符不是0
,就将totalSteps
加 1。这是因为每遇到一个非零字符,就意味着需要删除这一位数字才能使该数字最终变为 0。
- 通过内层的
-
返回结果:
- 循环结束后,函数返回
totalSteps
,这个值就是将数组中所有数字变为 0 所需删除的最少位数总和。
- 循环结束后,函数返回
知识点总结
在这道题的解题过程中运用了for循环和sprintf函数。- sprintf
是 C 语言标准库中的一个函数,它的功能是将格式化的数据写入到字符串中。其函数原型通常如下:
int sprintf(char *str, const char *format,...);
其中,str
是指向目标字符串的指针,也就是要将格式化后的内容存储到这个字符串所在的内存区域;format
是格式化字符串,用于指定输出的格式;后面的省略号(...
)表示可变参数列表,用于提供要按照指定格式进行格式化的数据。