zoukankan      html  css  js  c++  java
  • 算法问题拓展——kadane算法及其二维数组的扩展

      上次完成最大子序和算是对这类算法的入门,现在想要对其进行加深学习。


      最大子数组的问题里对我印象最深的就是动态规划的解决方法——“解其不同部分(即子问题),再根据子问题的解以得出原问题的”。这种解决方法十分常用,而其在一维数组中的总结以及最优解就是Kadane算法。

    Kadane算法

    //C++伪代码
    int
    kadane(){ int ans = n[0]; dp[0] = n[0]; for(int i = 1;i < strlen(n);i++){ dp[i] = Max(n[i],dp[i-1]+n[i]); ans = Max(dp[i],ans); } }

      作为最简洁的算法,我在这里先列上,java形式在之前的随笔中就有,但发现解释和我的理解有不一样的地方,这影响到我对二维数组的理解,所以在此重新学习一遍。

      首先是关注点。要着重注意:指定数组中某一个元素 n[i] 作为最大子序列的末尾元素时, 能找到的最大子数组的求和值是多少。这样但我们看第一个元素n[0]的时候,只需要关注其后一个元素即可;而在算子序和的时候,n[i...j]也只需要关注n[j+1]即可。意思就是n[i...j]中的最大子数组只会包含或不包含n[j+1]。如果包含,再看下一个元素。如果不包含,那么从n[j+2]再开始找即可。过程中记录出现的最大子序和。

    二维数组中用动态规划

      既然问题扩展了一个维度,那就只要找到子问题就还是能用动态规划。

      如果简单的说:将同一列的元素与前一行的元素相加得到一个一维数组,对一维数组进行Kadane算法就能找出最大子数组的和。但这样只是描述了过程,很难理解(不过对过程进行一次演绎后确实能理解不少,It just work)。

    public int kadane2d(int n[][]){
            int rows = n.length;
            int cols = n[0].length;
            int temp[] = new int[rows];
            int result;//maxSum
            for(int left = 0; left < cols ; left++){
                for(int i=0; i < rows; i++){
                    temp[i] = 0;
                }
                for(int right = left; right < cols; right++){
                    for(int i=0; i < rows; i++){
                        temp[i] += n[i][right];
                    }
                    int kadaneResult = kadane(temp);//currentSum
                    if(kadaneResult > result){
                        result = kadaneResult;
                    }
                }
            }
            return result;
        }

      时间复杂度近似O(n3)——O(cols*rows*cols)

      具体过程为Maximum Sum Rectangular Submatrix in Matrix dynamic programming/2D kadane(Youtube)。


      后记,记下自己的未实现过程。

      本来想着用递归和二分法来解决并节约时间复杂度,但解决时遇到问题,没法在二分后判断跨越中间的子数组的大小,所以宣告放弃。但或许什么时候想出来了也不失为一种解决方案。

      参考网上解题过程后,已经觉得找最大子数组问题是把我引入动态规划的一道经典例题,所以最后归纳的方案还是用了Kadane算法来解决。

  • 相关阅读:
    消息中间件
    线程以及多线程
    锁以及分布式锁
    并发以及高并发
    SpringBoot + SpringCloud学习踩坑实记
    公众号笔记: 2018年12月
    浅谈final关键字的用法
    浅谈static关键字的四种用法
    Linux常用的一些命令
    HTTPS
  • 原文地址:https://www.cnblogs.com/limitCM/p/10583311.html
Copyright © 2011-2022 走看看