最大子数组问题(分治法)--【算法导论】

原创 2014年01月07日 11:44:05

这题的思想是书上的(《算法导论》),代码当然也是按照书上伪码写出的;

之前已用动态规划解决这个问题,所以问题也不用多说,简述如下:

《算法导论》中引入这个问题是通过股票的购买与出售,经过问题转换,将前一天的当天的股票差价重新表示出来,即转为了一个最大子数组的问题,具体内容我不多说,转的内容是:

13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7

找到这连续的16个数里面的连续和最大的子数组;

说一下书中的思想吧(语言组织是书中的,自认总结不会比书上好):

假定我们要寻找子数组A[low..high]的最大子数组,使用分治法意味着我们要将子数组划分为两个规模尽可能相等的子数组。也就是说,找到子数组的中央位置,比如mid,然后求解两个子数组A[low..mid]和A[mid + 1..high]。所以,A[low..high]的任何连续子数组A[i..j]所处的位置必然是三种情况之一:

1.完全位于子数组A[low..mid]中, 因此low<=i<=j<=mid;

2.完全位于子数组A[mid + 1..high]中,因此mid<=i<=j<=high;

3.跨越了中点,因此low<=i<=mid<j<=high;

因此,A[low..high]的一个最大子数组所处的位置必然是这三种情况之一。实际上,A[low..high]的一个最大子数组必然是完全位于A[low..mid]中、完全位于A[mid + 1..high]中或者跨越中点的所有子数组中和最大者。

代码:

#include <iostream>

const int Infinite = -10000;
//int max_left = 0;
//int max_right = 0;

using namespace std;

int FindMaxCrossSubarray(int A[], int low, int mid, int high)  //跨越
{
    int left_sum = Infinite;
    int sum = 0;
    for (int i = mid; i >= low; i--)  //左半部的最大子数组
    {
        sum += A[i];
        if (sum >left_sum)
        {
            left_sum = sum;
            //max_left = i;
        }
    }

    int right_sum = Infinite;
    sum = 0;
    for (int i = mid + 1; i <= high; i++)  //右半部的最大子数组
    {
        sum += A[i];
        if (sum > right_sum)
        {
            right_sum = sum;
            //max_right = i;
        }
    }
    return left_sum + right_sum;
}

int FindMaxSubarray(int A[], int low, int high)
{
    int left_sum, right_sum, cross_sum;
    if (high == low)  //一个元素
    {
        return A[low];
    }
    else
    {
        int mid = (low + high) / 2; //分治
        left_sum = FindMaxSubarray(A, low, mid);  //前半部
        right_sum = FindMaxSubarray(A, mid + 1, high);  //后半部
        cross_sum = FindMaxCrossSubarray(A, low, mid, high);  //跨越前后

        if (left_sum >= right_sum && left_sum >= cross_sum)  //最大子数组在左边
            return left_sum;

        else if (right_sum >= left_sum && right_sum >= cross_sum)  //右边
            return right_sum;

        else  //跨越
            return cross_sum;
    }
}

int main()
{
    int a[] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
    //int a[] = {23, -4};
    int length = sizeof(a) / sizeof(int);

    cout<<FindMaxSubarray(a, 0, length - 1)<<endl;
    //cout<<"最大子序列的下标:"<<max_left<<"->"<<max_right;
    return 0;
}


 

欢迎指点,o(∩_∩)o

相关文章推荐

KNN与KD-tree

原文地址:http://blog.csdn.net/lanbing510/article/details/49926343 KNN最朴素的比较方法为轮询,改进方法kd-tree 写...

LeetCode(140) Word Break II

题目如下: Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where...

算法导论——分治法——最大子数组问题

好久没有写博客了。以后我会不定期地写一些算法的博客,分享一些算法的感想。以下的说法很多都是我自己的感想,肯定有很多不足的地方,希望大家指正。 今天把算法导论里面分治法这一章里面的第一个问题——最大子数...

[算法导论]分治法---最大子数组

分治策略---最大自子数组 一、分治策略的三个步骤 1、分解:将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小 2、解决:递归地求解出子问题。如果子问题的规模足够小...

「算法导论」:分治法求最大子数组

时间复杂度:o(nlgn)

最大子数组问题:分治法

  • 2014年05月31日 22:33
  • 103KB
  • 下载

算法导论之分治策略:最大子数组问题

分治策略
  • WSYW126
  • WSYW126
  • 2016年03月05日 21:00
  • 509

算法导论_最大子数组问题(分治策略)

package com.wzs; import java.util.Arrays; /** * 算法导论--page41 * * @author Administrator * */...
  • adam_zs
  • adam_zs
  • 2013年02月28日 22:51
  • 1803

算法导论学习:分治策略之最大子数组问题

对于分治策略,是算法中很重要的一个环节,它能够将一个很大的问题分解为一个个的小问题,从而降低求解难度。今天,我就对《算法导论》中的最大字数组问题进行分析,并给出书中伪代码的C/C++语言表现形式,同时...

【算法学习】最大子数组问题的分治法求解

最大子数组问题求解的是给定一个数组a[]0...n-1],求出它的一个子数组使得其所有元素的和加起来最大 如果使用暴力解法即枚举所有的子数组,则时间复杂度为O(n^2) 采用分治法,对一段数组a[...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:最大子数组问题(分治法)--【算法导论】
举报原因:
原因补充:

(最多只允许输入30个字)