递归思想-LeetCode解题java实现

1.1 递归介绍

递归是一种编程技巧,一种解决问题的思维方式;严格来说,递归并不是一种算法。简单地说,就是如果在函数中存在着调用函数本身的情况,这种现象就叫递归。

递归的思想就是,将大问题分解为小问题来求解,然后再讲小问题分解为更小的问题。这样一层一层的分解,直到问题规模被分解的足够小,不用继续分解,可以直接计算结果为止。

如果把这个一层一层分解过程画成图,他其实就是一棵树。我们给这棵树起一个名字,叫做递归树。
在这里插入图片描述在这里插入图片描述
递归在””的过程中,符合后进先出的规则,所以需要用一个堆栈的数据结构。递归过程中函数调用会自动产生栈帧,当函数帧栈的深度越来越大的时候,栈也越来越大,如果递归没有终止条件,就会爆栈。所有基于递归思想实现的算法,第一步要思考的就是递归的终止条件。

分治算法和动态规划很大程度上是递归思想基础上的,解决更具体问题的两类算法思想。

进一步剖析「递归」,先有「」再有「」,「递」的意思是将问题拆解成子问题来解决, 子问题再拆解成子子问题,…,直到被拆解的子问题无需再拆分成更细的子问题(即可以求解),「归」是说最小的子问题解决了,那么它的上一层子问题也就解决了,上一层的子问题解决了,上上层子问题自然也就解决了。

递归的一般结构:

void func()  { 
     if(符合边界条件)  { 
        /// 
        return; 
     } 
     
     //某种形式的调用 
     func(); 
} 

以如下代码为例:

以阶乘函数为例,如下, 在 factorial 函数中存在着 factorial(n - 1) 的调用,所以此函数是递归函数:

public int factorial(int n) {
    if (n < =1) {
        return 1;
    }
    return n * factorial(n - 1)
}

以6的阶乘f(6) 为例来看下它的「递」和「归」:
在这里插入图片描述
求解问题 f(6), 由于 f(6) = n * f(5), 所以 f(6) 需要拆解成 f(5) 子问题进行求解,同理 f(5) = n * f(4) ,也需要进一步拆分,… ,直到 f(1), 这是「递」,f(1) 解决了,由于 f(2) = 2 f(1) = 2 也解决了,… f(n)到最后也解决了,这是「归」,所以递归的本质是能把问题拆分成具有相同解决思路的子问题,。。。直到最后被拆解的子问题再也不能拆分,解决了最小粒度可求解的子问题后,在「归」的过程中自然顺其自然地解决了最开始的问题。

参考:https://www.jianshu.com/p/b2d2edb4ba5b

1.2 基本步骤

(1) 定义一个函数,明确函数功能

(2) 寻找问题与子问题之间的关系(递推公式)

(3) 将递推公式在定义的函数中实现

(4) 推导时间复杂度,判定是否可以接受,无法接受更换算法

1.3 代表题目

1.3.1 爬楼梯(#70)

class Solution {
        public int climbStairs(int n) {
            int[] stairs = new int[n + 1];
            return climb(n, stairs);
        }

        private int climb(int n, int[] stairs) {
            if (n == 1) return 1;
            if (n == 2) return 2;
            if (stairs[n] > 0) {
                return stairs[n];
            }
            stairs[n] = climb(n - 1, stairs) + climb(n - 2, stairs);
            return stairs[n];
        }
    }

1.3.2 青蛙跳台阶(#面试题10-II)

1.3.3 斐波那契数列(#509)

class Solution {
        public int fib(int N) {
            int[] fibs = new int[N + 1];
            return process(N, fibs);

        }

        private int process(int n, int[] fibs) {
            if (n == 0) return 0;
            if (n == 1) return 1;
            if (fibs[n] > 0) {
                return fibs[n];
            }
            fibs[n] = process(n-1, fibs) + process(n-2, fibs);
            return fibs[n];
        }
    }

1.4 触类旁通

1.4.1 反转二叉树(#226)

class Solution {
        public TreeNode invertTree(TreeNode root) {
            if (root == null) {
                return null;
            }
            TreeNode left = invertTree(root.left);
            TreeNode right = invertTree(root.right);
            root.left = right;
            root.right = left;
            return root;
        }
    }

1.4.2 路径总和(#112)

class Solution {
        public boolean hasPathSum(TreeNode root, int sum) {
            if (root == null) {
                return false;
            }
            if (root.left == null && root.right == null) {
                return root.val == sum;
            }
            int remain = sum - root.val;

            return hasPathSum(root.left, remain) || hasPathSum(root.right, remain);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值