问题描述
一个整数如果由相同的数字构成,则称为完美整数。例如:
1、11、333是完美整数。12、19、101是不完美整数。
现在,你需要计算给定区间 [x, y] 中有多少个整数是完美整数。
测试样例
样例1:
输入:
x = 1 ,y = 10
输出:9
样例2:
输入:
x = 2 ,y = 22
输出:10
思路
分析题目,将大问题分成多个小问题,分成是单位数或者多位数的情况;
- 单位数:使用
i/10 == 0来判断,并且计算个数。 - 多位数:
- ①计算整数的位数
- ②拆分每一位数字
- ③判断每个数是否相同
其中,多位数的情况见以下分析以及代码,例子为判断222是否为完美整数
多位数的情况分析
- ①计算整数的位数:
创建一个数组用于存储整数中的每个数字,数组长度 为 整数
i的位数dCount,其关系为10^(dC - 1) = i。(如222是3位数,其对应的最大值100是10^2,即dC整数的位数为3,i=222,100 = 10^2 = 10^(3-1) = 10^(dC-1))----> 整数的位数:
dC = Math.log10(i) + 1
int dCount = (int) Math.log10(i) + 1;
- ②拆分每一位数字
已知整数位数,用for循环遍历,每位数通过
num/Math.pow(10,dC-j-1)计算,即用num/10^(dC-j-1)。(如222,要取出第一个数2,会使用222/100,这是num=222,100=10^2=10^(3-1-j),j=0)通过
j的变化和每次取出前一个数将其减掉,num = num - digits[j] * dr,即num = num- num/dr * dr。(如222,num = 222,dC = 3,dr = 10^2 = 100,则num = num - (int)(num/dr) *dr = 222 - * (int)(222/100) * 100 = 222 - 2 * 100 = 222-200 = 22,则22为下一个num
int[] digits = new int[dCount];
int num = i;
// 拆分每一位数字,为 digits 数组
for(int j = 0;j < dCount;j++){
int dr = (int) Math.pow(10,dCount - j - 1);
// System.out.println("dr = " + dr);
digits[j] = num / dr;
num -= digits[j] * dr;
}
- ③判断每个数是否相同
当数组中前一个数和后一个数不相同时,通过
break跳出外层循环,该数不符合完美整数的定义;当数组中前一个数和后一个数相同时,依次遍历,直到数组的末尾,返回1则表示遍历成功,该数符合条件,令计数sum加一。
// 判断每个数字是否相同
for(int j = 0;j < digits.length-1;j++){
// 假设头一个数和下一个数不相等,则直接退出外层循环
if(digits[j] != digits[j+1]){
break;
}
if(j == digits.length-2){
System.out.println("成功");
return 1;
}
}
// 输出数组进行检查
System.out.println(Arrays.toString(digits));
return 0;
多位数的情况的完整测试代码:
import java.util.Arrays;
public class Main {
public static int solution1(int i){
int dCount = (int) Math.log10(i) + 1;
int[] digits = new int[dCount];
int num = i;
// 拆分每一位数字,为 digits 数组
for(int j = 0;j < dCount;j++){
int dr = (int) Math.pow(10,dCount - j - 1);
// System.out.println("dr = " + dr);
digits[j] = num / dr;
num -= digits[j] * dr;
}
// 判断每个数字是否相同
for(int j = 0;j < digits.length-1;j++){
// 假设头一个数和下一个数不相等,则直接退出外层循环
if(digits[j] != digits[j+1]){
break;
}
if(j == digits.length-2){
System.out.println("成功");
return 1;
}
}
System.out.println(Arrays.toString(digits));
return 0;
}
public static void main(String[] args) {
// System.out.println(solution1(222) );
}
}
完整代码
import java.util.Arrays;
public class Main {
public static int solution(int x, int y) {
// 如果是单个数,出现多少个就有多少个完美整数;如果不是单个数,那么当每个数是一样的 则是完美整数
int sum = 0;
for(int i = x;i <= y;i++){
// 单个数的情况
if(i/10 == 0){
sum++;
}
// 多个数的情况
else{
// 计算整数的位数。 dCount 表示有几位数字。如222/100,10^2,有3位。即 10^(dC - 1) = i ====》dC 为 该数字有几位
int dCount = (int) Math.log10(i) + 1;
int[] digits = new int[dCount];
int num = i;
// 拆分每一位数字
for(int j = 0;j < dCount;j++){
int dr = (int) Math.pow(10,dCount - j - 1);
digits[j] = num / dr;
num -=digits[j] * dr;
}
// 判断每个数字是否相同
for(int j = 0;j < digits.length-1;j++){
// 假设头一个数和下一个数不相等,则直接退出外层循环
if(digits[j] != digits[j+1]){
break;
}
if(j == digits.length-2){
sum++;
}
}
}
}
return sum;
}
public static void main(String[] args) {
// System.out.println(solution(1, 10) == 9);
System.out.println(solution(2, 22) == 10);
// System.out.println(solution(220, 222) );
}
}
知识点整理
- log函数:
int x = (int) Math.log10(i)-------log x = i - 指数函数:
int x = (int) Math.pow(10,i)------10^i = x -
拆分整数中的每一位数:
int[] digits = new int[dCount];
int num = i;
// 拆分每一位数字,为 digits 数组
for(int j = 0;j < dCount;j++){
int dr = (int) Math.pow(10,dCount - j - 1);
// System.out.println("dr = " + dr);
digits[j] = num / dr;
num -= digits[j] * dr;
}
用
num/10^(dC-j-1)。(如222,要取出第一个数2,会使用222/100,这是num=222,100=10^2=10^(3-1-j),j=0)通过
j的变化和每次取出前一个数将其减掉,num = num - digits[j] * dr,即num = num- num/dr * dr。(如222,num = 222,dC = 3,dr = 10^2 = 100,则num = num - (int)(num/dr) *dr = 222 - * (int)(222/100) * 100 = 222 - 2 * 100 = 222-200 = 22,则22为下一个num
-
输出数组进行检查:
System.out.println(Arrays.toString(digits));,直接输出 则结果是哈希码,并且数组中各元素的值,使用Arrays.toString(x)输出数组,并要求引入包名import java.util.Arrays;。 - 分类讨论,将大问题转换成多个小问题,再将小问题挨个解决。
感受
越做越娴熟,赞。由于Java方面比较不熟悉,将问题拆成挨个小问题后,在针对性的进行解决。参考每个小问题对应的解决方法,学习整理,并查看是否能解决当前我所面对问题,该如何调试能够解决问题,如果出现问题了,又该如何调试查找到问题所在,挨个尝试了,并找到最终的解决方案了。♥
参考: