Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

Follow up:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

这道题让求数组中和最大的子数组的和,类似这种“问题的子问题的最优解”问题首先想到的是使用动态规划的方法求解,使用动态规划的难点在于使用适当的dp数组写出问题的正确的状态转移方程,本题的状态转移方程可以表示为:dp[i]=max(dp[i-1]+nums[i],nums[i]),其中dp[i]表示数组中以nums[i]结尾的和最大的子数组的和。这个解法的时间复杂度是 O(n),内存消耗O(n)。代码如下maxSubArray_dp_normal函数所示。由于在计算dp[i]的时候只需要用到dp[i-1],所有可以用一个变量代替dp数组,进行了空间压缩,实现时间复杂度是 O(n),内存消耗O(1),是本题的最优解法,代码如maxSubArray_dp_selected函数所示。

动态规划:


//动态规划 时间O(n) 空间O(n)
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //return maxSubArray_dp_normal(nums);
        return maxSubArray_dp_seleted(nums);  
    }
    int maxSubArray_dp_normal(vector<int>& nums)
    {
        const int nums_size = nums.size();
        vector<int> dp = nums;//dp[i]表示以nums[i]结尾的和最大的子序列的和
        int res = dp[0];
        for(int i = 1;i<nums_size;++i)
        {
            dp[i] = max(dp[i-1]+nums[i],nums[i]);//状态转移方程 
            res = max(res,dp[i]);
        }
        return res;
    }
    //空间优化了的dp,时间O(n) 空间O(1)
    int maxSubArray_dp_seleted(vector<int> &nums)
    {
        const int nums_size = nums.size();
        int dp = nums[0];
        int res = dp;
        for(int i = 1;i<nums_size;++i)
        {
            dp = max(dp+nums[i],nums[i]);//状态转移方程 
            res = max(res,dp);
        }
        return res;
    } 
};

题目还要求我们用分治法 Divide and Conquer Approach 来解,这个分治法的思想就类似于二分搜索法,需要把数组一分为二,分别找出左边和右边的最大子数组之和,然后还要考虑最大和子数组同时跨越左右两个子数组的情况,具体是从中间开始向左右分别扫描,求出的最大值分别和左右两边得出的最大值相比较取三者最大的那一个,时间复杂度是O(nlogn),显然此种方法不是本题的最优解,分治法代码如下:

分治:


class Solution {
public:
    int maxSubArray(std::vector<int>& nums) {
        int nums_size = nums.size();
        return maxSubArray_div(nums,0,nums_size-1);
    }
    int maxSubArray_div(std::vector<int>& nums,int i,int j)
    {
        if(i>=j) return nums[i];
        int h = (j+i)/2;//也可以使用移位操作
        int left =  maxSubArray_div(nums,i,h);
        int right = maxSubArray_div(nums,h+1,j);
        int mid_value_right = nums[h];
        int r_sum = 0;
        for(int r = h;r<=j;++r)
        {
           r_sum+=nums[r];
           if(r_sum>=mid_value_right) mid_value_right=r_sum;
        }
        int mid_value_left = nums[h];
        int l_sum = 0;
        for(int l = h;l>=i;--l)
        {
            l_sum+=nums[l];
            if(l_sum>=mid_value_left) mid_value_left=l_sum;
        }
        int mid_value = mid_value_left + mid_value_right - nums[h];
        return max(max(left,right),mid_value);
    }  
};
 

[LeetCode] 53. Maximum Subarray 最大子数组 --动态规划+分治的更多相关文章

  1. [LeetCode] 53. Maximum Subarray 最大子数组

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  2. [leetcode]53. Maximum Subarray最大子数组和

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  3. LeetCode 53. Maximum Subarray最大子序和 (C++)

    题目: Given an integer array nums, find the contiguous subarray (containing at least one number) which ...

  4. 小旭讲解 LeetCode 53. Maximum Subarray 动态规划 分治策略

    原题 Given an integer array nums, find the contiguous subarray (containing at least one number) which ...

  5. [array] leetcode - 53. Maximum Subarray - Easy

    leetcode - 53. Maximum Subarray - Easy descrition Find the contiguous subarray within an array (cont ...

  6. Leetcode#53.Maximum Subarray(最大子序和)

    题目描述 给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大. 例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4], 连续子序列 [4,-1,2,1] ...

  7. leetcode 53. Maximum Subarray 、152. Maximum Product Subarray

    53. Maximum Subarray 之前的值小于0就不加了.dp[i]表示以i结尾当前的最大和,所以需要用一个变量保存最大值. 动态规划的方法: class Solution { public: ...

  8. 41. leetcode 53. Maximum Subarray

    53. Maximum Subarray Find the contiguous subarray within an array (containing at least one number) w ...

  9. LN : leetcode 53 Maximum Subarray

    lc 53 Maximum Subarray 53 Maximum Subarray Find the contiguous subarray within an array (containing ...

随机推荐

  1. javamail 附件以及正文加图片

    直接上代码 import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.uti ...

  2. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_05 IO字符流_2_字符输入流读取字符数据

    读取的文件有中文也有英文 强转为char类型 缓冲读取多个字符 使用string的构造方法转换为字符输出

  3. nginx proxy_pass 和 proxy_redirect

    proxy_pass:充当代理服务器,转发请求proxy_redirect:修改301或者302转发过程中的Location.默认值为proxy_redirect default. 例:locatio ...

  4. 解决Delphi窗体缩放の疑难杂症

    http://anony3721.blog.163.com/blog/static/511974201082235754423/ 解决Delphi窗体缩放の疑难杂症 2010-09-22 15:57: ...

  5. Java 基础-IO、stream 流、文件操作

    输入输出流的分类 在 java.io 包中,包含了输入输出操作所需的类. I/O 流可以安装不同的标准分类: 按照流的方向分类: 输入流:将信息从代码外部输入代码 输出流:将代码得到的数据输出到文件. ...

  6. c#处理bin文件

    1. fs.Position  写入的位置,从哪个位置开始写 fs.Write(byte1,0,byte1.Length); byte1写入的byte[], 写入内容从第几位开始取,length取多长 ...

  7. (selenium+python)_UI自动化01_Mac下selenium环境搭建

    前言 Selenium 是一个用于Web网页UI自动化测试的开源框架,可以驱动浏览器模拟用户操作.支持多种平台(Windows.Mac OS.Linux)和多种浏览器(IE.Firefox.Chrom ...

  8. LeetCode——142 设计链表2

    题目 代码 class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *fast = head, *slow ...

  9. windows10配置Docker容器独立IP地址互相通信

    Docker官方推荐我们通过端口映射的方式把Docker容器的服务提供给宿主机或者局域网其他容器使用.一般过程是: 1.Docker进程通过监听宿主机的某个端口,将该端口的数据包发送给Docker容器 ...

  10. 实列+JVM讲解类的实列化顺序

    刨根问底---类的实列化顺序 开篇三问 1什么是类的加载,类的加载和类的实列有什么关系,什么时候类加载 2类加载会调用构造函数吗,什么时候调用构造函数 3什么是实列化对象,实列化的对象有什么东西. 我 ...