首页 > 代码库 > 每天进步一点点——求最大子序列和问题
每天进步一点点——求最大子序列和问题
转载请说明出处:http://blog.csdn.net/cywosp/article/details/38493351
假设有如下整数数组 -10 5 0 8 -1 10 -10 100 -1 求其最大的子序列和。从该数组我们可以知道其子序列和最大的序列为5 0 8 -1 10 -10 100且等于112。(为方便起见,如果数组全是负数则最大和为0)
处理这个问题,我们可以有如下四种方法:
方法一:时间复杂度为O(N^3)
int MaxSubSum1(const std::vector<int>& vec)
{
int max = 0;
for (int i = 0; i < vec.size(); ++i) {
for (int j = 0; j < vec.size(); ++j) {
int sum = 0;
for (int x = i; x <= j; ++x) {
sum += vec[x];
}
if (sum > max) {
max = sum;
}
}
}
return max;
}
该方法是求出所有子序列的和,然后在得出最大的和。
方法二:时间复杂度为O(N^2)
int MaxSubSum2(const std::vector<int>& vec)
{
int max = 0;
for (int i = 0; i < vec.size(); ++i) {
int sum = 0;
for (int j = i; j < vec.size(); ++j) {
sum += vec[j];
if (sum > max) {
max = sum;
}
}
}
return max;
}
因为后一子序列的和为前面序列和加上后面一元素,所以在前面子序列和已被求出的情况下可以少一次循环
方法三:时间复杂度为O(N log(N))
int MaxSubSum3(const std::vector<int>& vec, int left, int right)
{
if (right == left) {
if (vec[left] > 0) {
return vec[left];
} else {
return 0;
}
}
int center = (right + left) / 2;
int left_max_sum = MaxSubSum3(vec, left, center);
int right_max_sum = MaxSubSum3(vec, center + 1, right);
int left_sum = 0;
int left_max = 0;
for (int i = center; i >= left; --i) {
left_sum += vec[i];
if (left_sum > left_max) {
left_max = left_sum;
}
}
int right_sum = 0;
int right_max = 0;
for (int i = center + 1; i <= right; ++i) {
right_sum += vec[i];
if (right_sum > right_max) {
right_max = right_sum;
}
}
return std::max(std::max(left_max_sum, right_max_sum), (right_max + left_max));
}
该方法是左右划分数组,然后递归分别求出每个被划分数组的最大和
方法四:时间复杂度为O(N)
int MaxSubSum4(const std::vector<int>& vec)
{
int sum = 0;
int max = 0;
for (int i = 0; i < vec.size(); ++i) {
sum += vec[i];
if (sum > max) {
max = sum;
} else if (sum < 0) {
sum = 0;
}
}
return max;
}
这种方法是最为高效的,一次扫描素组就能求出,具有这种特性的算法叫作联机算法(on-line algorithm)
#include <iostream> #include <vector> #include <stdlib.h> int main(int argc, char const *argv[]) { if (argc < 2) { std::cout << "./program int ... int" << std::endl; return -1; } std::vector<int> vec; vec.reserve(argc - 1); for (int i = 0; i < argc - 1; ++i) { vec.push_back(strtol(argv[i + 1], nullptr, 10)); } std::cout << MaxSubSum1(vec) << std::endl; std::cout << MaxSubSum2(vec) << std::endl; std::cout << MaxSubSum3(vec, 0, vec.size() - 1) << std::endl; std::cout << MaxSubSum4(vec) << std::endl; return 0; }
编译g++ -std=c++11 main.cc -o sum
运行./sum -10 5 0 8 -1 10 -10 100 -1
输出如下:
112
112
112
112
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。