动态规划算法之一——动态规划入门


用简单通俗易懂的话来记录自己对动态规划算法的理解

1.动态规划算法是什么

1.思想

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。

2.核心

根据定义,动态规划是把一个大问题拆解成一堆小问题,这个本身没啥问题,但是,这不是动态规划的核心思想,一个大问题之所以能用到“动态规划”解决,并不是因为它能拆解成一堆小问题,事实上啥大问题都能拆解成小问题。取决于该问题是否能用动态规划解决的这些“小问题”会不会被重复调用。

2.局限

动态规划对于解决多阶段决策问题的效果是明显的,但是动态规划也有一定的局限性。首先,它没有统一的处理方法,必须根据问题的各种性质并结合一定的技巧来处理;另外当变量的维数增大时,总的计算量及存贮量急剧增大。因而,受计算机的存贮量及计算速度的限制,当今的计算机仍不能用动态规划方法来解决较大规模的问题,这就是“维数障碍”

3.应用

1.斐波那契数列

1.兔子数列/楼梯数列

举个例子,有n个阶梯,一个人每一步只能跨一个台阶或是两个台阶,问这个人一共有多少种走法?
思路一:总结规律,归类斐波那契数列数列
1个阶梯:1
2个阶梯:2
3个阶梯:3
4个阶梯:5种
思路二:动态规划算法(将大问题分解为小问题)
设n个阶梯有f(n)种走访
n个阶梯:
最后一步走一个阶梯:f(n-1)
最后一步走两个阶梯:f(n-2)
那么n个阶梯就是f(n)=f(n-1)+f(n-1)。
同理:对于
n-1个阶梯:
也是f(n)= f(n-1)+f(n-2)
并且,至关重要的一点是:
f这个函数算法保持一致。
OK,那么接下来,让我们编码
方案一:递归解法

 public static void main(String[] args){
        MyClass myclass = new MyClass();
        System.out.println("resursion(3):"+myclass.recursion(3));
        System.out.println("resursion(4):"+myclass.recursion(4));
        System.out.println("resursion(5):"+myclass.recursion(5));
        long start = System.currentTimeMillis();
        long result = myclass.recursion(50);
        System.out.println("resursion(5" +
                "0):"+result+" costTime:"+(System.currentTimeMillis() - start));

    }

    public long recursion(long n) {
        if (n <= 0) {
            return 0;
        }
        if (n <= 2) {
            return n;
        }
        return recursion(n - 1) + recursion(n - 2);
    }

结果如下:

resursion(3):3
resursion(4):5
resursion(5):8
Disconnected from the target VM, address: '127.0.0.1:59282', transport: 'socket'
resursion(50):20365011074 costTime:38740
Process finished with exit code 0

大家可以看到,当递归次数50+的话,这个计算的时间复杂度是很高的,所以非最优解。
它的时间复杂度是O(2^n),空间复杂度O(1)。

方案二:非递归解法
用于减少递归解法的重复数值阶段,时间复杂度O(n)

public long nonRecusion(long n){

        if (n <= 2) {
            return n;
        }
        long  a =  1L;
        long  b = 2L;
        long result = 0L;
        for (int i = 3; i <= n; i++) {
           result = a + b;
           a= b;
           b = result;
        }
        return result;
    }

  System.out.println("resursion(3):"+myclass.nonRecusion(3));
  System.out.println("resursion(4):"+myclass.nonRecusion(4));
  System.out.println("resursion(5):"+myclass.nonRecusion(5));

   MyClass myClass = new MyClass();
   long start = System.currentTimeMillis();
   long result = myClass.nonRecusion(50);
   System.out.println("resursion(50):"+result+" costTime:"+(System.currentTimeMillis() - start));

结果:

resursion(3):3
resursion(4):5
resursion(5):8
resursion(50):20365011074 costTime:0

有没有觉得效率直线上升
方案三:矩阵法
先直接说这种算法的效率吧,O(logN),对,你没有看错,大河弯弯向东流,就是这么6.
这种算法原理简单,但是,直接分析,还有点难度,有机会在分析

4.站在巨人肩膀

https://www.zhihu.com/question/39948290

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值