* 面试题43:1—n整数中1出现的次数 (背!!!!!!!!)
* 题目:输入一个整数n,求1-n这n个整数中的十进制表示中1出现的次数
* 例如:输入12,1-12这些整数中包含1 的数字有1、10、11、12 1一共出现了5次(11算作2次)
* (求出任意非负整数区间的1出现的个数)
*
* 思路:总结规律发现: 时间复杂度O(k) k为位数
* 当前位的值 = 0时,1出现的次数为: 高位值*当前位位数
* 当前位的值 = 1时,1出现的次数为: 高位值*当前位位数 + 当前位数值 % 当前位位数 + 1
* 当前位的值 > 1时,1出现的次数为: (高位值 + 1)*当前位位数
*
* 例如:n = 21305 每一位出现1的情况统计
* 万位(>1):(21305 / 100000 + 1) * 10000 = 10000次
* 千位(=1):(21305 / 10000 ) * 1000 + 21305 % 1000 + 1 = 2306次
* 百位(>1):(21305 / 1000 + 1) * 100 = 2200次
* 十位(=0):(21305 / 100) * 10 = 2130次
* 个位(>1):(21305 /10 + 1) * 1 = 2131次
https://github.com/linpeiyou/CodingInterviews/blob/master/src/com/peige/algo/_43_NumberOf1.java
package Test;
public class No43NumberOf1Between1AndN {
/*
* 面试题43:1—n整数中1出现的次数 (背!!!!!!!!)
* 题目:输入一个整数n,求1-n这n个整数中的十进制表示中1出现的次数
* 例如:输入12,1-12这些整数中包含1 的数字有1、10、11、12 1一共出现了5次(11算作2次)
* (求出任意非负整数区间的1出现的个数)
*
* 思路:总结规律发现: 时间复杂度O(k) k为位数
* 当前位的值 = 0时,1出现的次数为: 高位值*当前位位数
* 当前位的值 = 1时,1出现的次数为: 高位值*当前位位数 + 当前位数值 % 当前位位数 + 1
* 当前位的值 > 1时,1出现的次数为: (高位值 + 1)*当前位位数
*
* 例如:n = 21305 每一位出现1的情况统计
* 万位(>1):(21305 / 100000 + 1) * 10000 = 10000次
* 千位(=1):(21305 / 10000 ) * 1000 + 21305 % 1000 + 1 = 2306次
* 百位(>1):(21305 / 1000 + 1) * 100 = 2200次
* 十位(=0):(21305 / 100) * 10 = 2130次
* 个位(>1):(21305 /10 + 1) * 1 = 2131次
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
No43NumberOf1Between1AndN number = new No43NumberOf1Between1AndN();
int n = 21305;
System.out.println("1出现的次数为:" + number.NumberOf1Between1AndN(n));
}
private int NumberOf1Between1AndN(int n) {
// TODO Auto-generated method stub
if(n <= 0) {
return 0;
}
int sum = 0;
for(int k = 1;n/k > 0;k *= 10) {
int mod = n/k % 10;
if(mod > 1) {
sum += ((n / (k * 10)) + 1) *k ;
}
else if(mod == 1) {
sum += (n / (k * 10))*k + (n % k) + 1;
}
//仅剩mod == 0
else{
sum += (n / (k * 10)) * k;
}
}
return sum;
}
}
* 面试题44:数字序列中某一位数字
* 题目:数字以0123447568934896378623,,,的格式化序列到一个字符序列中。
* 在这个序列中,第5位(从0开始计数)是5,第13位是1,第19位是4,等等。
* 请写一个函数,求任意第n位对应的数字。
*
* 思路:1-9 一位数 10-99 两位数 99--999三位数
***********一位数1开始 两位数 10开始 三位数100开始
* 1> 首先确定数字是几位数(一位数、两位数、三位数)
* 2>判断数字是哪一个数中
* 3>判断是数中的哪一位
*
* 例如: 1001位数字7
* 1> 确定是几位数 一位数n<9 两位数9<n<90*2+9=189 三位数189<n<900*3+189=2889
* 因为189<n = 1001<2889 所以是三位数
* 2> 确定是哪一个数 (1001-189)/3 = 270(取整)三位数中270
* 但是 前面还有两位数90个 一位数10个 所以是270+90=10=370 也就是第370个数
* 3> 确定是数中的哪一位 1001-189-270*3 = 2
* 若下标为0 则是第370个的下标为1的位置
*
* https://www.jianshu.com/p/0bbf1fcbe070
* https://blog.csdn.net/m0_37862405/article/details/80341260
package Test;
public class No44DigitInSequence {
/*
* 面试题44:数字序列中某一位数字
* 题目:数字以0123447568934896378623,,,的格式化序列到一个字符序列中。
* 在这个序列中,第5位(从0开始计数)是5,第13位是1,第19位是4,等等。
* 请写一个函数,求任意第n位对应的数字。
*
* 思路:1-9 一位数 10-99 两位数 99--999三位数
***********一位数1开始 两位数 10开始 三位数100开始
* 1> 首先确定数字是几位数(一位数、两位数、三位数)
* 2>判断数字是哪一个数中
* 3>判断是数中的哪一位
*
* 例如: 1001位数字7
* 1> 确定是几位数 一位数n<9 两位数9<n<90*2+9=189 三位数189<n<900*3+189=2889
* 因为189<n = 1001<2889 所以是三位数
* 2> 确定是哪一个数 (1001-189)/3 = 270(取整)三位数中270
* 但是 前面还有两位数90个 一位数10个 所以是270+90=10=370 也就是第370个数
* 3> 确定是数中的哪一位 1001-189-270*3 = 2
* 若下标为0 则是第370个的下标为1的位置
*
* https://www.jianshu.com/p/0bbf1fcbe070
* https://blog.csdn.net/m0_37862405/article/details/80341260
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(DigitAtIndex(9));
System.out.println(DigitAtIndex(188));
System.out.println(DigitAtIndex(1001));
}
public static int DigitAtIndex(int index) {
// TODO Auto-generated method stub
if(index < 0)
return (Character) null;
//计算是几位数
int digitNumbers = countOfNumbersFor(index);
//计算是第几个数
int beginNumber = beginNumber(digitNumbers,index);
String s = String.valueOf(beginNumber);
//计算是数的第几位
int digitIndex = digitIndex(beginNumber,digitNumbers,index);
return s.charAt(digitIndex)-48;//char型转换为int型
//获取字符串s的某一个索引值的元素 使用 charAt(int index) 返回字符char类型
}
//计算是数中的哪一位
private static int digitIndex(int beginNumber, int digitNumbers, int index) {
// TODO Auto-generated method stub
if(digitNumbers == 1)
return 0;
else if(digitNumbers == 2)
return index - 9 - (beginNumber-10)*2 -1;
else if(digitNumbers == 3)
return index - 189 - (beginNumber-10-90)*3 -1;
return -1;
}
//计算是哪一个数
private static int beginNumber(int digitNumbers, int index) {
// TODO Auto-generated method stub
if(digitNumbers == 1)
return index;
else if(digitNumbers == 2)
return (index - 9)/2 + 10;
else
return (index - 189)/3 +100;
}
//计算是几位数
public static int countOfNumbersFor(int index) {
// TODO Auto-generated method stub
if(index - 189 > 0)
return 3;
else if(index - 10 > 10)
return 2;
else
return 1;
}
}
自己写的简单代码 希望各位大牛批评指针 ^-^
* 面试题45:把数组排成最小的数
* 题目:输入一个正整数数组,把数组中所有数字拼接起来排成一个数,
* 打印能拼接处的所有数字中最小的一个。
* 例如:输入数组{3,32,321},则打印出这三个数字能排成的最小数字321323.
*
* 思路:1>首先将数值型转换为字符型数组
* 2>然后重写compare函数 使其能够对两个数值进行比较
* 3>再调用sort函数,对其进行排序 按照从小到大的顺序
* 4>最后将重新排好序的字符串使用StringBuilder的append将元素拼接到一起就可以了
package Test;
import java.util.Arrays;
import java.util.Comparator;
public class No45PrintMinNumber {
/*
* 面试题45:把数组排成最小的数
* 题目:输入一个正整数数组,把数组中所有数字拼接起来排成一个数,
* 打印能拼接处的所有数字中最小的一个。
* 例如:输入数组{3,32,321},则打印出这三个数字能排成的最小数字321323.
*
* 思路:1>首先将数值型转换为字符型数组
* 2>然后重写compare函数 使其能够对两个数值进行比较
* 3>再调用sort函数,对其进行排序 按照从小到大的顺序
* 4>最后将重新排好序的字符串使用StringBuilder的append将元素拼接到一起就可以了
*
* */
public static void main(String[] args) {
// TODO Auto-generated method stub
No45PrintMinNumber p = new No45PrintMinNumber();
int[] array = {3,32,321};
System.out.println("排出的最小的数:"+p.PrintMinNumber(array));
}
//将数组中的元素组合出最小的数
private String PrintMinNumber(int[] array) {
// TODO Auto-generated method stub
if(array == null|| array.length == 0)
return null;
int length = array.length;
String[] str = new String[length];
StringBuilder sb = new StringBuilder();
//将int型转变为str[]数组
for(int i = 0; i < length;i ++)
str[i] = String.valueOf(array[i]);
//将数组元素进行排序,根据其大小进行排序
//重写compare中的定义 然后调用sort函数进行排序
Arrays.sort(str, new Comparator<String>() {
@Override
public int compare(String s1,String s2) {
String c1 = s1 + s2;
String c2 = s2 + s1;
return c1.compareTo(c2);
}
});
for(int i = 0;i < length; i++)
sb.append(str[i]);
return sb.toString();
}
}