今天我们讨论的算法是最大子数组问题。

  首先我定义了一个类用来保存最大子数组的开始位置索引、结束位置索引和该数组的和。代码如下:

class MaximumSubArray
{
private:
int begin; //开始位置索引
int end; //结束位置索引
int sum; //和
public:
void setBegin(int Begin)
{
begin=Begin;
}
void setEnd(int End)
{
end=End;
}
void setSum(int Sum)
{
sum=Sum;
} int getBegin()
{
return begin;
}
int getEnd()
{
return end;
}
int getSum()
{
return sum;
}
};

  该算法采用分治策略,我们先讨论最大子数组跨越中点位置的情况:

MaximumSubArray FindMaxCrossingSubArray(int *numArray,int low,int middle,int high)
{
MaximumSubArray max;
int leftsum=numArray[middle];
int maxleft=middle;
int sum=;
for(int i=middle;i>=low;i--)
{
sum+=numArray[i];
if(sum>=leftsum)
{
leftsum=sum;
maxleft=i;
}
}
int rightsum=numArray[middle+];
int maxright=middle+;
sum=;
for(int j=middle+;j<=high;j++)
{
sum+=numArray[j];
if(sum>=rightsum)
{
rightsum=sum;
maxright=j;
}
}
max.setBegin(maxleft);
max.setEnd(maxright);
max.setSum(leftsum+rightsum);
return max;
}

  接下来是二分法求最大子数组:

MaximumSubArray FindMaximumSubArray(int *numArray,const int low,const int high)
{
MaximumSubArray max;
if(high==low)
{
max.setBegin(low);
max.setEnd(high);
max.setSum(numArray[low]);
return max;
}
if(high-==low)
{
max.setBegin(high);
max.setEnd(high);
max.setSum(numArray[high]);
return max;
}
int middle=(low+high)/;
MaximumSubArray left=FindMaximumSubArray(numArray,low,middle);
MaximumSubArray right=FindMaximumSubArray(numArray,middle,high);
MaximumSubArray cross=FindMaxCrossingSubArray(numArray,low,middle,high);
if(left.getSum()>=right.getSum()&&left.getSum()>=cross.getSum())
max=left;
else if(right.getSum()>left.getSum()&&right.getSum()>=cross.getSum())
max=right;
else
max=cross;
return max;
}

注意:

  该书中的伪代码并没有以下这段

if(high-==low)
{
max.setBegin(high);
max.setEnd(high);
max.setSum(numArray[high]);
return max;
}

因为在算法递归到数组中只有两个元素的时候,算出的middle值和low值是一样的(& 索引为0和1的两个元素),所以,在high==low的时候去索引小的元素,在high-1=low的时候取索引大的元素,避免无限循环。

以上代码,请放到如下注释的位置,保存为SubArray.h

#include <stdlib.h>

namespace dksl
{
//
//
//
}

  下面是程序测试代码及运行结果:

#include "stdafx.h"
#include <iostream>
#include "SubArray.h" using namespace std;
using namespace dksl;
int _tmain(int argc, _TCHAR* argv[])
{
int a[] = {, -, -, , -, -, -, , , -, , -, -, , -, };
MaximumSubArray max=FindMaximumSubArray(a,,);
cout<<"begin:"<<max.getBegin()<<endl;
cout<<"end:"<<max.getEnd()<<endl;
cout<<"sum:"<<max.getSum()<<endl;
system("PAUSE");
return ;
}

该算法的时间复杂度为θ(nlogn)

《算法导论》——MaximumSubArray的更多相关文章

  1. B树——算法导论(25)

    B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...

  2. 红黑树——算法导论(15)

    1. 什么是红黑树 (1) 简介     上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...

  3. 基本数据结构(2)——算法导论(12)

    1. 引言     这一篇博文主要介绍链表(linked list),指针和对象的实现,以及有根树的表示. 2. 链表(linked list) (1) 链表介绍      我们在上一篇中提过,栈与队 ...

  4. 堆排序与优先队列——算法导论(7)

    1. 预备知识 (1) 基本概念     如图,(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树.树中的每一个结点对应数组中的一个元素.除了最底层外,该树是完全充满的,而且从左向右填充.堆的数组 ...

  5. quickSort算法导论版实现

    本文主要实践一下算法导论上的快排算法,活动活动. 伪代码图来源于 http://www.cnblogs.com/dongkuo/p/4827281.html // imp the quicksort ...

  6. [算法导论]二叉查找树的实现 @ Python

    <算法导论>第三版的BST(二叉查找树)的实现: class Tree: def __init__(self): self.root = None # Definition for a b ...

  7. 算法导论第十八章 B树

    一.高级数据结构 本章以后到第21章(并查集)隶属于高级数据结构的内容.前面还留了两章:贪心算法和摊还分析,打算后面再来补充.之前的章节讨论的支持动态数据集上的操作,如查找.插入.删除等都是基于简单的 ...

  8. 算法导论----VLSI芯片测试; n个手机中过半是好的,找出哪些是好手机

    对于分治(Divide and Conquer)的题目,最重要是 1.如何将原问题分解为若干个子问题, 2.子问题中是所有的都需要求解,还是选择一部分子问题即可. 还有一点其实非常关键,但是往往会被忽 ...

  9. [置顶] 《算法导论》习题解答搬运&&学习笔记 索引目录

    开始学习<算法导论>了,虽然是本大部头,可能很难一下子看完,我还是会慢慢地研究的. 课后的习题和思考有些是很有挑战性的题目,我等蒻菜很难独立解决. 然后发现了Google上有挺全的algo ...

  10. (搬运)《算法导论》习题解答 Chapter 22.1-1(入度和出度)

    (搬运)<算法导论>习题解答 Chapter 22.1-1(入度和出度) 思路:遍历邻接列表即可; 伪代码: for u 属于 Vertex for v属于 Adj[u] outdegre ...

随机推荐

  1. svn hooks post-commit钩子自动部署

    #!/bin/sh #修改为服务编码 export LANG=zh_CN.utf- #Set variable REPOS="$1" REV="$2" SVN= ...

  2. 多线程练习,深刻体会了一次变量的BUG.

    package ltb20180106; public class TestBankThread { private int deposit=0;//注意全局变量的摆放. public TestBan ...

  3. 53题看透java线程

    1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速.比如,如果一个线程完成 ...

  4. DS二叉树--Huffman编码与解码

    题目描述 1.问题描述 给定n个字符及其对应的权值,构造Huffman树,并进行huffman编码和译(解)码. 构造Huffman树时,要求左子树根的权值小于.等于右子树根的权值. 进行Huffma ...

  5. Reg2Bat_By Slore(生成同名bat文件,支持XP WIN7 WIN7X64).vbs

    原文http://slore.blogbus.com/logs/52627038.htmlSlore编写的这个reg文件转换为bat文件,是逐句转换的,不是通过批处理生成临时reg文件然后导入的方法, ...

  6. mybatisz中一个可以替代between..and 的技巧

    用mybatis进行时间段筛选时,如果,查询本日,本月的信息量,我们可以使用like concat()函数来替换between..and <select id="queryMyStaf ...

  7. 事件之onTouch方法的执行过程 及和 onClick执行发生冲突的解决办法

    转载:http://blog.csdn.net/jiangwei0910410003/article/details/17504315#quote 博主推荐: 风萧兮兮易水寒,“天真”一去兮不复还.如 ...

  8. [UE4]在蓝图中判断一个对象是否有效

  9. Java基础:IO流之字节流和字符流

    1. 流的概念 流(stream)的概念源于UNIX中管道(pipe)的概念.在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备.外部文件等. 一个流,必有源端和目的端 ...

  10. Redis-Migrate-Tool 使用详解

    注意:目前不支持4.0.X及以上的redis使用 Redis 集群迁移工具,基于redis复制,快速,稳定. github链接:https://github.com/vipshop/redis-mig ...