算法(-):递归

先问个问题:递归思想难吗?有的人说,递归不就是自己调用自身嘛,有什么难的;有的人说,我擅长递归,写代码会显得短小精悍。然而总有那么一些人说递归好难,太难理解了。平常我也刷一些算法,有的题大概明白可以用递归,结果揉了半天才写出来。感觉递归下去把我弄懵逼了。

递归难在哪里?递归的思想和我们的正常思维是相反的。我们通常是从上往下的思维,而递归是从下往上的思维。有啥解决办法呢,两个字:练题。记住:我们写算法是通过计算机来执行的,虽然我们不好理解,但是对于计算机而言,这都不是事。。

递归算法解决问题的特点:

  • 递归就是方法里调用自身;
  • 在使用递归策略时,必须有个明确的递归结束条件,称为递归出口;
  • 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序;
  • 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等,所以一般不提倡用递归算法设计程序。

递归过程中,找好递归的出口是至关重要的。而且每次进行自身调用时通常都要使问题规模有所减少,从而能到满足递归出口的条件。

递归的经典示例


  • 示例一:求n得阶乘
    问题描述: 给定一个正整数n,求n的阶乘。

递归算法:

public int factorial(int n) {
        //递归出口
        if(n == 1) {
            return 1;
        }
        //问题的规模n逐渐减小,直到n等于1.
        return n * factorial(n - 1);
    }

非递归算法:

public int factorial(int n) {
        int result = 1;
        for(int i = 1; i <=n; i++) {
            result *= i;
        }
        return result;
    }
  • 示例二:上台阶的所有走法?
    问题描述: 有n阶台阶,一个人每次可以走1步或者2步,请问有多少种走法?

递归算法:

public int step(int n) {
        //终止条件
        if(n == 1)
            return 1;
        //终止条件
        if(n == 2) {
            return 2;
        }
        return step(n -1) + step(n - 2);
    }

非递归算法:

public int step(int n) {
        //借助于队列实现的,用其他的数据结构也可以的
        Queue<Integer> queue = new LinkedList<>();
        queue.add(n);
        int count = 0;
        while(!queue.isEmpty()) {
            int value = queue.poll();
            if(value == 1)
                count += 1;
            else if(value == 2) {
                count += 2;
            }else {
                queue.add(value-1);
                queue.add(value-2);
            }
        }
        return count;

    }

注:其实第二题用动态规划法能有更好地解决方案。等大家了解了动态规划法之后,再想想。。

  • 示例三:求链表的所有元素之和
    问题描述:有一个链表,其中头结点为head,求所有节点的元素之和。

节点的数据结构如下:

class ListNode{
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
    }
}

递归算法:

public int nodeSum(ListNode head) {
    if(head == null) {
        return 0;
    }
    return head.val + nodeSum(head.next);

}

非递归算法:

public int nodeSum(ListNode head) {
    int sum = 0;
    ListNode p = head;
    while(p != null) {
        sum += p.val;
        p = p.next;
    }
    return sum;
}

总结:递归是一种比较好的解决问题的方案,如果能够熟练掌握,算法水平绝对能上一个档次。上面主要给一些简单的使用递归的示例。在大部分的算法题中。递归通常会和分治法、动态规划法等结合使用的。做题时多画些图,有助于理解递归,祝咱们都更进一步!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值