根据剑指offer的思路可以分为以下三个步骤(数字n是k位,数字n最高位是h):
1. 计算最高位出现1的次数。若最高位为1,则最高位出现1的次数为除最高位以外的数值+1。例如1132,最高位出现1的次数为132+1=133。
2. 剩余情况划分为h+1段,对于其中的h段,计算(k-1)位1出现的次数。将数字划分h+1段,除去第一段外的h段都可以用排列组合计算。例如2136,可以分为1-136,137-1136,1137-2136,需要计算后两段个十百位1的个数。计算公式为:h*(k-1)*10^(k-2),含义为选中k-1位中的任意一位设置为1,其余位数自动变换。
3. 将2中的第1段进行迭代。
三个部分的count求和,得到answer。
public static int NumberOf1Between1AndN_Solution(int n){
//异常输入单独处理
if(n<=0) return 0;
//临时变量
int nTmp=n;//n的替身
int numberLength=0;//n的位数
int highestBit=0;//n的最高位
//三个count,分别代表最高位、除最高位的其它位、第一段分别出现1的个数
int highestBitCount=0,otherBitCount=0,firstPhaseCount=0;
//计算临时变量
while(nTmp!=0){
highestBit=nTmp%10;//记录最高位
nTmp/=10;
numberLength++;//计算n的位数
}
//只有一位的数字单独处理
if(numberLength==1) return 1;
//最高位1个数计算
if(highestBit==1){
highestBitCount=n-highestBit*(int)(Math.pow(10,numberLength-1)+0.5)+1;
}
else if(highestBit>1){
highestBitCount=(int)(Math.pow(10,numberLength-1)+0.5);
}
//其它位1个数计算
if(numberLength>1){
otherBitCount=highestBit*(numberLength-1)*(int)(Math.pow(10,numberLength-2)+0.5);
}
//第一段迭代
firstPhaseCount=NumberOf1Between1AndN_Solution(n-highestBit*(int)(Math.pow(10,numberLength-1)+0.5));
//最终结果
return highestBitCount+otherBitCount+firstPhaseCount;
}