Bootstrap

leetcode之递归刷题总结1

leetcode之递归刷题总结1

1-递归乘法
题目链接:

思路:让B-1乘A并递归下去,递归的结果加上A,就是B乘A。

AC代码如下:

class Solution {
    public int multiply(int A, int B) {
        if(B==0){
            return 0 ;
        }
        return A + multiply(A,B-1) ;
    }
}

在这里插入图片描述
2-预测赢家
题目链接:题目链接戳这里!!!

思路:如果是偶数个数字,先抓的一定赢,要是奇数个,则递归求出A选择的值-B选择的值得到的最大值。大于等于0,则A赢,反之B赢。

AC代码如下:

class Solution {
    public boolean PredictTheWinner(int[] nums) {
        if((nums.length&1)==0){
            return true ;
        }
        return f(nums, 0, nums.length-1)>=0 ;
    }
    public int f(int [] nums, int l, int r){
        if(l==r){
            return nums[l] ;
        }
        int left = nums[l]-f(nums,l+1,r) ;
        int right = nums[r]-f(nums,l,r-1) ;
        return Math.max(left, right) ;
    }
}

在这里插入图片描述
3-斐波那契数列
题目链接:题目链接戳这里!!!

AC代码如下:

class Solution {
    public int fib(int n) {
        if(n==0){
            return 0 ;
        }
        if(n==1){
            return 1 ;
        }
        return fib(n-1)+fib(n-2) ;
    }
}

在这里插入图片描述
4- 2的幂
题目链接:题目链接戳这里!!!

AC代码如下:

通过位运算递归实现:

class Solution {
    public boolean isPowerOfTwo(int n) {
        if(n<=0){
            return false ;
        }
        return ((n-1) & n) ==0 ;
    }
}

在这里插入图片描述
不停的除以2,判断是不是不等于1的奇数也可以。

class Solution {
    public boolean isPowerOfTwo(int n) {
        if(n<=0){
            return false ;
        }
        if(n==1){
            return true ;
        }
        if((n&1)==1){
            return false ;
        }
        return isPowerOfTwo(n/2) ;
    }
}

在这里插入图片描述
5-找出游戏的获胜者
题目链接:题目链接戳这里!!!!+

思路:约瑟夫环问题,记住递推表达式就可以。
AC代码如下:

class Solution {
    public int findTheWinner(int n, int k) {
        if(n==1){
            return n ;
        }
        return (findTheWinner(n-1, k) + k-1)%n + 1 ;
    }
}

在这里插入图片描述
非递归代码如下:

class Solution {
    public int findTheWinner(int n, int k) {
        int s=1 ;
        for(int i=2; i<=n; i++){
            s = (s+k-1)%i+1;
        }
        return s ;
}
}

6-翻转字符串暖
题目链接:题目链接戳这里!!!

基础题,就是双指针,要求不开辟额外的存储空间

AC代码如下:

class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length-1 ;
        while(l<r){
            char temp = s[l] ;
            s[l] = s[r] ;
            s[r] = temp ;
            l++;
            r--;
        }
    }
}

在这里插入图片描述
7. 3的幂
题目链接:题目链接戳这里!!!

思路:不停除3递归,如果不能对3取余,则不是3的幂,如果一直能递归到1,则是3的幂。

class Solution {
    public boolean isPowerOfThree(int n) {
        if(n<=0){
            return false ;
        }
        if(n==1){
            return true ;
        }
        if(n%3!=0){
            return false ;
        }
        return isPowerOfThree(n/3) ;
    }
}

在这里插入图片描述
8. 4的幂
题目链接:题目链接戳这里!!!

思路和上题一样,不再赘述!

class Solution {
    public boolean isPowerOfFour(int n) {
        if(n<=0){
            return false ;
        }
        if(n==1){
            return true ;
        }
        if(n%4!=0){
            return false ;
        }
        return isPowerOfFour(n/4) ;
    }
}

在这里插入图片描述

9.统计好数字的数目
题目链接:题目链接戳这里!!!

思路:这题用到了快速幂,就是5的奇数次放乘4的偶数次方,但是直接算次方算不出来的,必须用快速幂。

AC代码如下:

class Solution {
    public int countGoodNumbers(long n) {
        long mod = 1000000007;
        long even = n / 2 ;
        long odd = n / 2 ;
        if((n&1)==1){
            odd ++ ;
        }
        long ans1 = pow(5,odd,mod) ;
        long ans2 = pow(4,even,mod) ;
        return (int)((ans1*ans2)%mod) ;
    }
    public long pow(long base, long x, long mod){
        long ans = 1 ;
        while(x != 0){
            if((x&1)==1){
                ans = (ans*base)%mod;
            }
            base = base * base %mod;
            x = x / 2 ;
        }
           return ans ;
    }
 
}

在这里插入图片描述
10-2出现的次数
题目链接:题目链接戳这里!!!

这题最容易想到的是转换成字符串,暴力统计2的个数,不过这种大数会超时,AC不了。

思路:
首先2的个数就是数字n的各个…千,百,十,个位上的2的个数之和。

举例:

1、当n的第一个数字为1时,以n = 168为例。

168中2的个数 = 0~99中2的个数 + 100~168中2的个数

容易看出100~168中2的个数 = 0~68中2的个数

所以:168中2的个数 = 0~99中2的个数 + 0~68中2的个数

2、当n的第一个数字为2时,以n = 268为例。

268中2的个数 = 0~199中2的个数 + 200~268中2的个数

200~268中2的个数 = 百位上2的个数 + 十位上2的个数 + 个位上2的个数

=69(百位) + 0~68中2的个数(十位 + 个位)

所以:268中2的个数 = 0~199中2的个数 + 0~68中2的个数 + 69

3、当n的第一个数字大于2时,以n = 468为例。

只有在200~299时n的百位上才有2,共100个

0-99,100-199,200-299,300-399 中十位上2的个数都相同

400~468中2的个数 = 0 ~ 68中2的个数

所以n = 468中2的个数 = 100 + 4 * 0~99中2的个数 + 0~68中2的个数

AC代码如下:

class Solution {
    public int numberOf2sInRange(int n) {
        String s = String.valueOf(n) ;
        int len = s.length() ;
        if(n<2){
            return 0 ;
        }
        if(n<12){
            return 1 ;
        }
        if(n<20){ //该递归只能处理两位数以上的
            return 2 ;
        }
        int first = (s.charAt(0) - '0') ;
        int power = (int)Math.pow(10,len-1) ;
        int last = Integer.parseInt(s.substring(1));
        if(first==1){
            return numberOf2sInRange(power-1) + numberOf2sInRange(last) ;
        }else if(first==2){
            return numberOf2sInRange(2*power-1)+numberOf2sInRange(last) + last+1 ;
        }else{
            return power + first*numberOf2sInRange(power-1)+numberOf2sInRange(last) ;
        }
        
    }
}

在这里插入图片描述
11-数字1的个数
题目链接:题目链接戳这里!!!

思路:这题和上题思路一样,还稍微简单一点。
我们判断首位是不是1,然后递归下去即可。

若首位是1,例如168
则168中1的个数=0-99中1的个数+100-168中1的个数
也就是等于0-99中1的个数+百位上1的个数69+0-68中1的个数
若首位不是1,例如268
则268中1的个数=百位上1的个数100+2倍的0-99上1的个数+0-68中1的个数

AC代码如下:

class Solution {
    public int countDigitOne(int n) {
        String s = String.valueOf(n) ;
        int len = s.length();
           if(n<1){
            return 0 ;
        }
        if(n<10){
            return 1 ;
        }
        int power = (int)Math.pow(10,len-1) ;
        int first = (s.charAt(0)  - '0') ;
        int last = Integer.parseInt(s.substring(1)) ;
        
        if(first==1){
            return countDigitOne(power-1) + countDigitOne(last) + last + 1 ;
        }else{
            return power + first*countDigitOne(power-1)+countDigitOne(last) ;
        }
}
}

在这里插入图片描述

;