zoukankan      html  css  js  c++  java
  • 【LeetCode & 剑指offer刷题】分治法题2:42 连续子数组的最大和(53. Maximum Subarray)

    【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

    53. Maximum Subarray

    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.
     
     
    //最大子数组问题
     
    /*
    方法:动态规划
    f(i) = a[i], i <0或f(i-1) <= 0;
    f(i) = f(i-1) + a[i], i!=0, f(i-1) > 0
    max(f[i]) 不太好想
    */
     
     
    //方法一:动态规划
    //不断更新sum和ans   sum = max(sum + num, num)
    //分析:时间复杂度On(线性)
    class Solution
    {
    public:
        int maxSubArray(vector<int>& nums)
        {
            int ans = INT_MIN, sum = 0;
            for (int num : nums)
            {
                sum = max(sum + num, num);
                ans = max(ans, sum);
            }
            return ans;
        }
    };
     
    //方法二:分治法
    //具体过程:将数组分为左子数组、右子数组、跨越中点的子数组问题
    //分析:时间复杂度O(nlgn)
    //参考资料:《算法导论》
    class Solution
    {
    public:
        int maxSubArray(vector<int>& a)
        {
            return findMaxSubArray(a, 0, a.size()-1);//递归入口
        }
       
        //递归函数:找a[left...right]的最大子数组(归并排序和快速排序中也用到了分治法,可以类比一下)
        int findMaxSubArray(vector<int>& a, int left, int right)//递归函数
        {
            if(right == left) return a[left];
           
            int mid = (left+right)/2;
            int left_sum = findMaxSubArray(a, left, mid);
            int right_sum = findMaxSubArray(a, mid+1, right);
            int cross_sum = findMaxCrossingSubArray(a, left, mid, right);
            return max(max(left_sum, right_sum), cross_sum);
           
        }
        //找跨中点的最大子数组,我们只需找出形如A[i.. mid] A[mid+ 1. .j] 的最大子数组,然后将其合并即可。
        int findMaxCrossingSubArray(vector<int>& a, int left, int mid, int right)
        {
            int left_sum,sum,right_sum;
            sum = 0;
            left_sum = a[mid];//初始化为参与计算的第一个元素  
            for(int i = mid; i>=left; i--)//从中间往左边遍历
            {
                sum += a[i];
                if(sum>left_sum) left_sum = sum;
            }
           
            sum = 0;
            right_sum = a[mid+1];//初始化
            for(int j = mid+1; j<=right; j++) //从中间往右边遍历
            {
                sum += a[j];
                if(sum>right_sum) right_sum = sum;
            }
            return (left_sum+right_sum);
           
           
        }
    };
     
  • 相关阅读:
    2013腾讯编程马拉松初赛第〇场(3月20日)湫湫系列故事——植树节 HDOJ 4503
    组合模式(Composite)
    Git Push 避免用户名和密码方法
    [Yii2] 快速套模板,加载JS,CSS(HTML标签<base>)
    phpstorm 2016.2.x 最新版激活方法
    PHP实现四种基本排序算法
    linux下查看负载均衡的两种方法
    Redis各类型应用场景
    HTTP协议2:请求、响应、缓存 2017-03-16 11:20 197人阅读 评论(0) 收藏
    HTTP协议1:工作原理 2017-03-16 11:18 39人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/wikiwen/p/10229476.html
Copyright © 2011-2022 走看看