算法学习之动态规划

今天在练习的一道算法题是求连续子数组的最大和。
题目描述:给定一个数组arr,数组中的元素有整数也有负数,数组中的一个或者连续多个数组成一个子数组。

求所有子数组里面的最大和。
在这里插入图片描述
当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?
本篇只讨论用动态规划的算法解决问题。
动态规划其实没有想象中的困难和复杂,首先,动态规划的定义:
动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
而动态规划的基本基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。
与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。
能采用动态规划求解的问题的一般要具有3个性质:
(1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
(2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
(3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)
回到本题,比如这个数组
{1,-2,3,10,-4,7,2,-5},最大连续子数组是{3,10,-4,7,2},和为18,
不过这个求解过程我们不需要知道最大连续子数组的范围,只要知道值是18就可以。
动态规划的思想就是找到子结构的关系。
我们可以这么切入这个关系结构,如果我们有个序列{1,-2,3},显然最大子序列是{3},如果我们在这个序列后面再加入一个数t,我们怎么去求加入一个数之后新的序列的连续子序列{1,-2,3,t}的最大和?这就需要抓住“连续” 这个特征,设以t为序列尾的最大子序列和为sum,则我们可以很直观地看出sum=max{3+t,t},这样理解起来很简单,因为3就在t前面,而我们已经知道以3为结尾的最大连续子序列和就是3,这个3就是t绕不过去的一个坑。
知道这个关系后我们就可以由题目推出这样一个式子;
设F[n]为下标为n结尾的连续子序列最大和,数组名为num
推出:F[n]=max{F[n-1]+num[n]}
看到这个式子
由这个关系我们就可以很自然地去求解这个问题。
提交的代码为:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class Main {


public static int getMax(int a,int b)
{if(a>b)return a;
else return b; }


public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        while(in.hasNextInt()) {
            int line = in.nextInt();
            int[] data = new int[line];
            for (int i = 0; i < line; i++) {
                data[i] = in.nextInt();}
            System.out.println(Find(data));
        }}

public static int Find(int[] array) {
            if(array.length == 0) return 0;
            int[] dp = new int[array.length];
            dp[0] = array[0];
            int max = Integer.MIN_VALUE;
            for(int i = 1;i < dp.length;i++){
                dp[i] = Math.max(array[i],dp[i - 1] + array[i]);
                if(dp[i] > max) max = dp[i];
            }
            return max;
        }
    }

牛客网显示的测试结果为通过率90%,暂时不知道是哪里出了问题。

发布了47 篇原创文章 · 获赞 1 · 访问量 1297

猜你喜欢

转载自blog.csdn.net/weixin_41750142/article/details/96480847
今日推荐