一、问题描述
小C对“好数”非常感兴趣,她定义一个不含前导零的正整数为“好数”,如果它的所有数位最多包含两种不同的数字。例如,数字 23,2323,9,111,和 101 都是好数。现在小C想知道,从1到n之间有多少个好数。
例如:当n=110时,所有的1位数、2位数,以及一些3位数(如 100, 101)都是好数,一共有102个。
二、测试样例
样例1:
输入:
n = 110
输出:102
样例2:
输入:
n = 1000
输出:352
样例3:
输入:
n = 1
输出:1
三、思路
所有的1位数、2位数以及一些3位数(如100,101)是确定已知的好数,所以如果n<=101时,好数的个数就是n本身。
而n>101时,就要另外考虑,此时已经有101个好数,接下来从102开始到n找出接下来的好数。把这些单独的数按照位数分开,把对应的数字放入哈希表,接下来比较哈希表的key数组的长度是否小于等于2。
四、代码
方法1
public static int solution(int n) {
int cnt=0;
if(n<=101){
cnt=n;
}
else {
cnt=101;
for(int i=102;i<=n;i++){
HashMap<Character,Integer> hash=new HashMap<>();
char[] ch=String.valueOf(i).toCharArray();
for(char a:ch){
hash.put(a, hash.getOrDefault(a, 0) + 1);
}
if(hash.size()<=2){
cnt++;
}
}
}
return cnt;
}
方法2
public static int solution(int n) {
int cnt=0;
if(n<=101){
cnt=n;
}
else {
cnt=101;
for(int i=102;i<=n;i++){
HashMap<Integer,Integer> hash=new HashMap<>();
int[] num=String.valueOf(i).chars().toArray();
for(int j:num){
hash.put(j, hash.getOrDefault(j, 0) + 1);
}
if(hash.size()<=2){
cnt++;
}
}
}
return cnt;
}
五、代码详解
方法1:用字符型的哈希表保存
if(n<=101){
cnt=n;
}
如果n<=101,那么从1到n的数全部是好数,所以好数个数是n。
HashMap<Character,Integer> hash=new HashMap<>();
新建字符型型的哈希表
char[] ch=String.valueOf(i).toCharArray();
valueOf()将数字i先转成字符串,toCharArray()将字符串转成字符型数组。
for(char a:ch){
hash.put(a, hash.getOrDefault(a, 0) + 1);
}
用getOrDefault()获取原本的value值,在此基础上加一。
if(hash.size()<=2){
cnt++;
}
用size()获取哈希表长度,如果所有数位最多包含两种不同的数字,那么哈希表长度不超过2,此时该数字为好数。
方法2:用数字型的哈希表保存
HashMap<Integer,Integer> hash=new HashMap<>();
新建数字型的哈希表
int[] num=String.valueOf(i).chars().toArray();
valueOf()将数字i先转成字符串,chars()返回字符串每个字符的ASCII值,即IntStream流,toArray()再将IntStream转成数字数组。
六、函数的使用
- 字符型哈希表的创建
- 数字转成字符串
- 哈希表的添加
- 哈希表获取key对应的value值
- 哈希表获取表的长度
- 字符串转成IntStream
- IntStream转成数字数组