[剑指offer]大可日常打卡-递归

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。

扫描二维码关注公众号,回复: 2901433 查看本文章

思路: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);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/hellodake/article/details/81661543