优雅的实现递归

有些时候写递归比循环的方法更简便一些,只是如果随便写个递归,勉强完成了功能,但是代码是有些别扭,比如方法太长,没有明确的顺序,想到哪写到哪。

实际上递归是有比较经典的写法,可以让代码看起来更易读。

什么是递归

递归的定义:一种计算过程,如果其中每一步都要用到前一步或前几步的结果,称为递归的

我们知道递归要满足两个条件:

  • 必须有一个终止计算的规则
  • 每次调用自己,必须在某种意义上更趋近解

递归模板

1 写递归终止条件

2 处理递归逻辑

3 如果有需要,处理递归结果


    /**
     * 递归调用的最深层次,不一定是整数,但是需要自己判断
     */
    private static final int MAX_LEVEL = 100;

    /**
     * 递归模板,自己修改方法名称
     * @param level  当前递归所处的层级,方便知道自己的位置。
     * @param results 每一层递归对应的结果 , 也可以是Map,一方面用来保存每一层的结果,另外可以用于调试递归代码
     * @param params 每次进行递归处理的参数
     */
    public static void recursion(int level, Collection results, String... params) {
        // 1. 满足递归终止的条件
        if (level > MAX_LEVEL){
            return;
        }

        // 2. 如果不需要终止递归,进行递归真正要做的事情
        Object processedData = processData(level, params);
        results.add(processedData);

        // 3. 进行递归
        recursion(level+1,results,params);

        // 4. 是否对最后的数据做一些处理
        doSomethingIfNeed();

    }

案例

斐波那契数列

import java.util.HashMap;
import java.util.Map;

/**
 * @author : aihe aihe.ah@alibaba-inc.com
 * @date : 2020/2/17 8:28 上午
 * 使用场景:
 * 功能描述:
 * 斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
 *
 * F(0) = 0,   F(1) = 1
 * F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
 */
public class FabDemo {
    public static void main(String[] args) {
        HashMap result = new HashMap();
        int fab = fab(0, result, 5);
        System.out.println(fab);
        System.out.println(result);
    }

    /**
     * 斐波那契数递归求解
     * F(N) = F(N - 1) + F(N - 2)    1
     * F(N - 1) = F(N - 2) + F(N - 3)  2
     * ...
     * F(2) = F(1) + F(0)    ...  N-1
     * F(1) = 1   N
     * F(0) = 0   N + 1
     *
     * @param level
     * @param result
     * @param n
     */
    public static int fab(int level, Map result, int n) {
        // level = n
        if (n == 1) {
            return 1;
        }

        // level == n + 1
        if (n == 0) {
            return 0;
        }

        int fabN = fab(level + 1, result, n - 1) + fab(level + 2, result, n - 2);
        result.put(n,fabN);
        return fabN;
    }

}

二叉树的前序遍历

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [1,2,3]
public class TreeTraverseDemo {

    public List<Integer> preorderTraversal(TreeNode root) {
        List result =  new LinkedList<Integer>();
        doPreOrder(result,root);
        return result;
    }

    /**
     * 先序遍历(Pre-order),按照根左右的顺序沿一定路径经过路径上所有的结点。在二叉树中,先根后左再右。巧记:根左右。
     * 1. 找终止条件,即当前节点为空,则终止继续遍历
     * 2. 处理逻辑: 将当前节点加入集合中
     * 3. 继续递归
     * @param list
     * @param root
     */
    public void doPreOrder(List<Integer> list,TreeNode root){
        if(root == null){
            return;
        }
        list.add(root.val);
        doPreOrder(list,root.left);
        doPreOrder(list,root.right);
    }


    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }
    }
}

最后

这里主要就是想介绍下递归的解题流程,模板根据具体的场景稍作修改,思考每次处理是否采用相同的方法,编写时:

方法体:
- 首先,终止的条件是什么
- 具体做了什么事
- 是否要对结果进行处理
- 继续递归(调用方法体)
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容