题目描述:求从1 到 n 中1出现的次数
夏都:首先请大家看一下以下的几个输出结果
0 --- 0
9 --- 1
99 --- 20
999 --- 300
9999 --- 4000
99999 --- 50000
999999 --- 600000
9999999 --- 7000000
对于一个任意的数,从1到n中的次数,比如n为abcdefg和从0000000abcdefg中1出现的次数一样,即输入结果为n位数,则对0n的每个数左边补0使其位数和n的位数相匹配。
对于从1到n中出现的次数,我们不妨先考虑一些特殊的值
一位数的范围09,这其中1出现1次99可以视为00
两位数的范围099,其中个位和十位分别在09的之间变化,对于0099,忽略掉十位的影响,个位中1出现的次数为:10*1即10次,接下来考虑十位的影响,十位不为1时,对结果无影响,十位为1时,结果+1,十位为1共出现10次,因此099中1出现的个数为20次
接下来考虑0999,忽略掉百位的影响,十位都是从0099进行变化,因此,十位和个位中出现的次数为2010即200次,接下来考虑百位的影响,百位不为1时,对结果无影响,百位为1的数共出现100次,因此0~~999中1出现的次数为200+100==300次依次进行递推可以得到,对于0到9···9(n个9) 可以得出结论 1的出现次数为
接下来我们考虑一个输入为abcdefg,我们可以把这个数分为两个部分0000000到(a-1)999999, 和a000000到abcdefgh,接下来考虑一下a的值
a为1时,0000000到(a-1)999999即可用上面的公式计算得出,对于a000000到abcdefgh,考虑a所在位的影响,a一共出现bcdefgh+1次,接下来,忽略a所在位的影响,剩下的数和从000000到bcdefgh的结果一致,递归调用即可,故此,当a==1时,最终结果= 600000 + bedefgh +1 + 递归计算(bcdefgh)
当a不为1时,对于0000000到(a-1)999999,忽略掉a所在位的影响,其余位从0到999999循环a次,结果为
a600000,由于a>1,所以结果要加上1000000,1在a的位共出现次,接下来考1000000虑a000000到abcdefgh,由于a!=1,所以其结果=递归计算(bcdefgh),故此,a不为1时候的计算结果= a*600000 + 1000000 + 递归计算(bcdefgh)
总结尾,对于一个n位数(,首位为1时,结果为
首位不为1时,设首位为x,则结果为
public static int NumberOf1Between1AndN_Solution(int n) { if( n == 0 || n == 1 ) return n; if(n>1&&n<10) return 1; String num = String.valueOf(n); if( num.charAt(0) == '1' ) { return (int) ((num.length()-1) * Math.pow(10, num.length()-2) + Integer.parseInt(num.substring(1)) + 1 + NumberOf1Between1AndN_Solution(Integer.parseInt(num.substring(1)))); }else { return (int) ((num.charAt(0) - '0') * (num.length()-1) * Math.pow(10, num.length()-2) + Math.pow(10, num.length()-1) + NumberOf1Between1AndN_Solution(Integer.parseInt(num.substring(1)))); } }
第一次写,没什么经验,希望大家多提意见。