剑指offer——递归

(一)剑指Offer10-I.斐波那契数列

在这里插入图片描述

class Solution {
    public int fib(int n) {
        int[] save = new int[101];
        save[0]=0;
        save[1]=1;
        save[2]=1;
        for (int i = 3; i <= n; i++) {
            save[i] = (save[i-1]+save[i-2])%1000000007;
        }
        return save[n];
    }
}

(二)剑指Offer10-II.青蛙跳台阶问题

在这里插入图片描述
基本思路:
到达最终台阶的方法有两种,即从倒数第一个台阶跳一下、或是从倒数第二个台阶跳两下。于是问题又转化为了跳到倒数第一个台阶有多少中可能、调到倒数第二个台阶有多少种可能。一次地柜,直到问题归到跳到第一个台阶或调到倒数第二个台阶有多少种可能,就终止递归。

class Solution {
    public int numWays(int n) {
        int a = 1, b = 1, sum;
        for(int i = 0; i < n; i++){
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }
        return a;
    }
}

递归的题目往往可以使用动态规划缩短运行时间,下面是动态规划的代码:

public int numWays(int n) {
        if(n == 0 || n == 1){
            return 1;
        }
        int[] cases = new int[n+1];
        cases[0] = 1;
        cases[1] = 1;
        for(int i = 2; i <= n; i++){
            cases[i] = (cases[i-1] + cases[i-2])% 1000000007;
        }
        return cases[n] ;
    }

(三)剑指 Offer 16. 数值的整数次方

在这里插入图片描述
基本思路:
1.如果直接递归求n次方,这道题会超时。
2.可以采用快速幂法,即:
在这里插入图片描述

class Solution {
    public double myPow(double x, int n) {
        //将指数位转化为二进制,每一位都用小一位的值来获得
        //首先列举特殊情况:
        if(x == 1){
            return 1;
        }
        if(x == -1){
            if(n % 2 == 0){
                return 1;
            }else{
                return -1;
            }
        }
        if(x > 0 && n == Integer.MIN_VALUE){
            //避免无穷小
            return 0;
        }
        if(n == 0){
            return 1;
        }
        //预先提取符号位,使数值为正
        double sign = (n>=0 ? 1:-1);
        double res = 1;
        int num = (sign >= 0) ? n: -n;
        double cur = 1;//存储当前位数所对应的值
        
        while(num > 0){
            if(num == Math.abs(n)){
                cur *= x;
            }else{
                cur *= cur;
            }
            if((num & 0x1) != 0){
                res *= cur;
            }
            num = num >>> 1;
            
        }
        return (sign >= 0)? res:(1/res);
        // return res;
    }
}

(四)剑指 Offer 38. 字符串的排列

在这里插入图片描述
基本思路:这一道题牵扯到回溯问题,故选用递归的方法。由于要排列所有的情况,我们可以对于一个字符串,将所有的位都方法第一位排列一次,然后将后面的位都以相同的方法再次排列。

class Solution {
    public String[] permutation(String s) {
        //每次固定一个字符,然后递归
        List<String> list = new ArrayList<>();
        if(s.length() == 0){
            return list.toArray(new String[0]);
        }
        char[] words = s.toCharArray();
        dfs(words,0,list,"");
        return list.toArray(new String[list.size()]);
    }
    void dfs(char[] words,int start,List<String> list, String head){//上一轮中被固定的元素
        //停止条件
        if(start == words.length){

                list.add(head);
        }
        HashSet<Character> set = new HashSet<>();
        //声明在这里,如果前面已经有过这个组合会直接删除掉。

        for(int i = start; i < words.length; i++){//把每一位挪到第一个,然后判断后面的排列组合
                if(set.contains(words[i])){
                    continue;
                }
                set.add(words[i]);
                char tmp =  words[start];
                words[start] = words[i];
                words[i] = tmp;
                dfs(words,start+1,list,head+words[start]);
                tmp =  words[start];
                words[start] = words[i];
                words[i] = tmp;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值