剑指Offer面试题(第二十七天)面试题43、44、45

 * 面试题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();
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_43137176/article/details/89476870