43.1~n整数中1出现的次数
题目描述:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
思路:遍历?每一个都算一下?暴力拆解!
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
if(n<1){
return 0;
}
int sum=0;
for(int i=1;i<=n;i++){
sum+=get1num(i);
}
return sum;
}
public static int get1num(int n){
String str=String.valueOf(n);
char[] chars=str.toCharArray();
int num=0;
for(int i=0;i<chars.length;i++){
if(chars[i]=='1'){
num++;
}
continue;
}
return num;
}
}
寻找新解法:从数字规律着手明显提高时间效率
设N=abcde,其中abcde分别为十进制中各位上的数字。
如果要计算百位上1出现的次数,它要受到三方面的影响:百位上的数字,百位以下的数字,百位以上的数字。
- 如果百位上为0,比如12063,百位上可能出现1的次数由更高位决定,100-199,1100-1199,2100-2199,……11100-11199,一共1200个。由更高的数字决定,等于高位数字乘以当前位数(100);
- 如果百位上为1,比如12163,百位上可能出现1的次数不仅受高位影响,还受低位影响,100-199,1100-1199,2100-2199,……11100-11199,12100-12163,高位数字乘以百位+低位数字+1;
- 如果百位上大于1(2-9),则百位上出现1的情况仅由高位决定,12263,100-199,1100-1199,2100-2199,……11100-11199,12100-12199,一共1300个,(高位数字+1)*100。
当前位i的范围-1,10,100,...
比如12063当前位100,高位12063/(100*10);低位12063%100;当前位数字(12063/100)%10。
高位:n/(i*10);低位:n%i;当前位数字:(n/i)%10
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int count=0;
int i=1; //当前位,从个位开始算
int current=0;
int after=0; //低位
int before=0; //高位
while((n/i)!=0){
current=(n/i)%10;
before=n/(i*10);
after=n%i;
if(current==0){
count+=before*i;
}else if(current==1){
count+=before*i+after+1;
}else{
count+=(before+1)*i;
}
i=i*10;
}
return count;
}
}
10.斐波那契数列
题目一:斐波那契数列
题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39。
思路:f(n)=0 n=0;
f(n)=1 n=1;
f(n)=f(n-1)+f(n-2) n>1
public class Solution {
public int Fibonacci(int n) {
if(n==0){
return 0;
}
if(n==1){
return 1;
}
return Fibonacci(n-1)+Fibonacci(n-2);
}
}
题目二:青蛙跳台阶问题
题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路:如果只有一级台阶的话,那么只有一种跳法;如果是两级台阶,那么既可以一级一级跳,也可以一下跳两级。接下来我们来讨论如果是n级台阶,如果第一步跳一级,那么跳法就是剩下的n-1级跳法数目,如果第一步跳两级,那么跳法数目就是剩下的n-2级跳法数目。
public class Solution {
public int JumpFloor(int target) {
if(target==0){
return 0;
}
if(target==1){
return 1;
}
if(target==2){
return 2;
}
return JumpFloor(target-1)+JumpFloor(target-2);
}
}
题目三:变态跳台阶
题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:
f(1)=1
f(2)=f(2-1)+f(2-2)
f(3)=f(3-1)+f(3-2)+f(3-3)
.....
f(n)=f(n-1)+f(n-2)+...+f(n-n)
等于n的时候,有n种跳法,1级,2级...n级
f(n)=f(n-1)+f(n-2)+...+f(n-n)=f(0)+f(1)+f(2)+...+f(n-1)
f(n-1)=f(0)+f(1)+f(2)+...+f(n-2)
所以,f(n)=2*f(n-1)
即f(n)=1 (n=0)
f(n)=1 (n=1)
f(n)=2*f(n-1) (n>=2)
public class Solution {
public int JumpFloorII(int target) {
if(target<=0){
return 1;
}else if(target==1){
return 1;
}
return 2*JumpFloorII(target-1);
}
}
牛客剑指offer
1.矩形覆盖
题目描述:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
思路:斐波那契数列。
public class Solution {
public int RectCover(int target) {
if(target==0){
return 0;
}else if(target==1){
return 1;
}else if(target==2){
return 2;
}else{
return RectCover(target-1)+RectCover(target-2);
}
}
}