递归总结

递归

最近刷算法刷到了递归和回溯我总结了一下一篇博客

首先,要了解递归就要知道递归是什么?

递归是什么?

**程序调用自身的编程技巧称之为递归。一个函数在运行中直接或者间接的调用自身就称之为一种方法。**它通常把一个大型复制的问题一层一层转为一个与原问题相似较小问题来解决

简单地来说,递归就是运行时自己调用自己,当满足一定的条件的时候就会跳出去

不过构成递归需要具备的条件:

  1. 子问题必须和原问题为同样的问题
  2. 不能无限的调用本身,须要有一个出口。

说了这么多可能都绕晕了 那我们看一个例子:

输入一个数n 求1+2+3+…+n

遇到递归的问题首先我们要 分解问题将一个大问题逐步成为一个一个小问题

我们可以将 1+2+3+…n分解成:

(n)+(1+2+…+n-1)

​ (n)+(n-1)+(1+2+…+n-2)

我们可以推出:1+2+…+n 可以逐步分解为一个一个数相加,下面看代码

private static int helper(int n) {
    if(n==1){
        return 1;
    }
    return n+helper(n-1);
}
public static void main(String[] args) {
        System.out.println(helper(100));
    }

在这里插入图片描述

可能这个例子过为简单,我们看下面一个例子

下面我们再来看一个经典的递归问题:斐波那契数列

斐波那契数列的是这样一个数列:1、1、2、3、5、8、13、21、34…,即第一项 f(1) = 1,第二项 f(2) = 1…,第 n 项目为 f(n) = f(n-1) + f(n-2)。求第 n 项的值是多少。

首先我们要将问题分解 但是题目已经给出了 f(n)=f(n-1)+f(n-2)

然后确定终止条件 因为题目定义都是从1-n 所以可能n-1 和n-2可能会小于0但是我们如果将循环从3开始

下面我们可以看终止条件

防止元素<0因此我们要设立终止条件

if(i==1){
    return 1;
}
if(i==2){
    return 2;
}

然后我们可以看一下递归的代码

return dfs(i-1)+dfs(i-2);

代码如下:

private static int dfs(int i) {
    if(i==1){
        return 1;
    }
    if(i==2){
        return 2;
    }
    return dfs(i-1)+dfs(i-2);
}

组合问题

给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。

示例:

输⼊: n = 4, k = 2

输出:

[

[2,4],

[3,4],

[2,3],

[1,2],

[1,3],

[1,4],

]

首先我们分析一下问题就是从1…n选出k个数 然后数去全部组合

从题目我们就可以得到终止条件了

if(当前递归深度==k){
	将这个结果之一保存在res(集合)之中
	return ;
}

然后我们可以将这个问题抽象成一个树,然后可以理解递归!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3xshiSe-1620997721037)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20210514194500299.png)]

从这课数我们可以看出如果深度等于k我们就终止条件停止递归

从左→右我们可以发现n可以发现这个是个循环,并且我们选了该数就不能再选,index就是避免重复选的 下面是伪代码

private static void helper(int k, int n,int index) {
    if(当前递归深度(当前结合的数量)==k){
		将这个结果之一保存在res(集合)之中
		return ;
	}
    for (int i = index; i <= n; i++) {
        将元素添加至集合中
         helper(k,n,index+1);
        将元素从集合中移除
    }
}

下面我们来看代码

   private  void helper(int k,int n,int index) {
        if(k==path.size()){
            res.add(new ArrayList<>(path));
            return ;
        }
        for (int i = index; i < n; i++) {
//            将元素添加至集合中
            path.add(i+1);
             helper(k,n,i+1);
//            将元素从集合中移除
            path.remove(path.size()-1);
        }
    }

这里我们可以优化一下空间

因为调用方法的时候k ,n 都是不会变的值我们可以作为全局变量,这样就可以节约空间

总结

如果我们要使用递归解决问题必须要满足:

  • 可以将一个大问题切分成一个一个一样的小问题来求解
  • 必须有终止条件

如果有回溯我们画树来加深理解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值