剑指offer第二版——面试题43(java)

面试题:1~n整数中1出现的次数

题目:

输入一个整数n,求1~n这n个整数的十进制表示中1出现的次数。

如输入12,1~12这些整数中包括1的数字有1、10、11和12,1一共出现了5次

【思路】

剑指offer上的解释有点看不懂囧,参考:https://www.cnblogs.com/wangkundentisy/p/8946858.html

对于一个形如xxxx的数,如要计算1出现在十位的数的个数,即xx1x的个数,分为三种情况

① xxab,a>1

a>1时,令a=1,则无论前面的两位xx取什么,都有相应的10个数可与之组合(如前面取23,后面可有10~19与其组合为2310~2319)

此时的数的取值为(xx+1)*10^(2-1)  ——xx+1是因为,若xx为22,则可从0开始取值,一直到22,实际是23个取值;10^(2-1)是因为在十位上时,位置标志为2,然而与之相对应的只有10个数,需要2-1

② xxab,a=1

a=1时,a只有一种取值,即1,且受后面b的影响,与①的区别主要在于:当xx取到最高时(如2315时,23固定后,只能从10~15=6个数,而2325可从10~19=10个数),不再是10个数都是可取的,因此,分开计算

此时数的取值为(xx)*10^(2-1)+(b+1) ——前面xx其实是代表的xx-1+1,指的是从0开始取值,直到最高位-1(xx-1),当xx取最高位时,后面只能取10~1b——b+1个数

③ xxab,a=0

a=0时,xx0b,此时xx只能取到0~(xx-1)——共xx种取值,每种取值对应10^(2-1)个数

此时数的取值为(xx)*10^(2-1) ,当xx取最高位时,十位上无法出现1(因为超过了数本身)

【方法】

所以总的来说,对于从右到左数的第i位(位上数为x),出现1的次数为:

① x>1,(高位+1)*10^(i-1) 

② x=1,(高位)*10^(i-1)+(低位+1)

③ x=0,(高位)*10^(i-1)

public class Q43 {
	public static void main(String[] args) {
		int a = 10000;
		System.out.println(howManyOne(a));
		
		
	}

	public static int howManyOne(int x) {
		// 如果是个位数,只出现1次
		if(x<10) {
			return 1;
		}
		int left = 0;
		double count = 0;
		int re = x;
		int sum = 0;
		while(re!=0) {
			left = re%10;
			re = re/10;
			
			// 当前位的数字==1
			if(left==1) {
				sum = (int) (sum + re*Math.pow(10, count)+x%Math.pow(10, count+1));
			
			// 当前位的数字==0
			}else if(left==0) {
				sum = (int) (sum + re*Math.pow(10, count));
				
			// 当前位的数字>1
			}else {
				sum = (int) (sum + (re+1)*Math.pow(10, count));
			}
			count++;
		}
		return sum;
	}
}

【其他】

如果要计算其他数字出现的次数也是相同的,只是把用于比较的1改为该数(1~9)即可

如果要计算0出现的次数,会有所不同,在最后需要把当0出现在第一位的次数减掉

	public static int howManyZero(int x) {
		// 如果是个位数,只出现1次
		if(x<10) {
			return 1;
		}
		int stad = 0;
		int left = 0;
		double count = 0;
		int re = x;
		int sum = 0;
		while(re!=0) {
			left = re%10;
			re = re/10;
			
			// 当前位的数字==0
			if(left==stad) {
				sum = (int) (sum + re*Math.pow(10, count)+x%Math.pow(10, count+1));
			
			// 当前位的数字!=0
			}else {
				sum = (int) (sum + (re+1)*Math.pow(10, count));
			}
			count++;
		}
		return sum-(int) ((re+1)*Math.pow(10, count-1));
	}

 

你可能感兴趣的:(剑指offer第二版)