本章简述
通过前面第二章节的叙述,描述了算法设计对程序员的日常影响:算法上的灵机一动可以使程序更加简单。但是本章内容将会发现算法设计的一个不那么常见但更富于戏剧性的贡献:复杂深奥的算法有时可以极大地提高程序性能。
问题及简单算法
本章引入的问题来自一维的模式识别,问题的输入是具有n个浮点数的向量x,输出是输入向量的任何连续子向量中的最大和。
例如,如果输入向量包含以下 N = 10 个元素:
arr[N] = { 31, -41, 59, 26, -53, 58, 97, -93, -23, 84 }
那么该程序的输出为x[2…6]的总和,即187。
该问题分为以下几种情况:
- 当所有数都是正数时,此时最大子向量就是整个输入向量;
- 当所有数都是负数时,此时最大子向量就是空向量,总和为0;
- 当输入向量正负均有时,此时最大子向量需要特殊处理;
对该问题,本章讨论了4种算法,性能逐步提高。
- 算法1的时间复杂度为T(n)=O(n^3);
- 算法2及2b的时间复杂度为T(n)=O(n^2);
- 算法3的时间复杂度为T(n)=O(nlogn);
- 算法4的时间复杂度为T(n)=O(n);
下面将下面4个算法,详细给出程序实现。
立方算法
完成该问题的浅显程序对所有满足区间的(i,j)的整数对进行迭代。对每个整数对,程序都要计算x[i…j]的总和,并检验是否大于迄今为止的最大总和。算法程序实现如下:
/************************************************************************/
/*
* 《编程珠玑》第八章 算法设计技术
* 问题:输入具有n个浮点数的向量x ,输出向量中任何连续子向量中的最大和
* 算法一:T(n) = O(n^3)
*/
/************************************************************************/
#include <iostream>
#include <cstdlib>
using namespace std;
/************************************************************************/
/*
* 算法说明:
*(1)当所有输入都是正数时,最大子向量就是整个输入向量
*(2)当所有输入都是负数时,最大子向量是空向量,和为0
*(3)当前处理情况是,输入序列有正有负
*/
/************************************************************************/
float maxSubSum(const float *arr, const int N , int &begin , int &end)
{
float maxsofar = 0 ;
for (int i = 0; i < N; i++)
{
for (int j = i; j < N; j++)
{
float sum = 0;
for (int k = i; k <= j; k++)
{
sum += arr[k];
}
if (sum > maxsofar)
{
maxsofar = sum;
begin = i;
end = j;
}
}
}
return maxsofar;
}
const int N = 10;
const float arr[N] = { 31, -41, 59, 26, -53, 58, 97, -93, -23, 84 };
int main()
{
cout << "The input numbers are: " << endl;
for (int i = 0; i < N; i++)
cout << arr[i] << "\t";
cout << endl << "The max sum is : " ;
int begin = -1, end = -1;
cout << maxSubSum(arr, N , begin , end) <<endl;
cout << "The position is : " << begin << "\t" << end << endl;
system("pause");
return 0;
}
平方算法1
对于之前的立方算法性能不尽如人意,下面有一个明显的方法可以使其运行起来快得多,
时间: 2024-10-13 12:59:15