c++分别设计时间复杂度为θ(n²)、θ(nlogn)和 θ(n)的多项式时间算法求解最大和子数组问题。并随机产生规模为n=1000,10000.100000, 1000000的输入实例。输出最大子数组的左右下标和其元素之和。并比较各算法在各输入实例规模所运行时间。给出完整代码
时间: 2025-06-25 07:28:22 浏览: 12
### C++实现最大和子数组问题的不同时间复杂度算法
以下是针对最大和子数组问题的三种常见解决方案及其对应的C++代码实现,分别具有 \( \theta(n^2) \), \( \theta(n\log n) \), 和 \( \theta(n) \) 的时间复杂度。
---
#### 方法一:\( \theta(n^2) \) 时间复杂度
该方法通过两重嵌套循环枚举所有可能的子数组并计算其和来找到最大值。虽然简单直观,但在大规模数据集上效率较低。
```cpp
#include <iostream>
#include <vector>
#include <cstdlib> // For rand()
using namespace std;
pair<int, pair<int, int>> maxSubArrayQuadratic(const vector<int>& nums) {
int maxSum = INT_MIN;
int startIdx = 0, endIdx = 0;
for (int i = 0; i < nums.size(); ++i) {
int currentSum = 0;
for (int j = i; j < nums.size(); ++j) {
currentSum += nums[j];
if (currentSum > maxSum) {
maxSum = currentSum;
startIdx = i;
endIdx = j;
}
}
}
return {maxSum, {startIdx, endIdx}};
}
```
此方法的时间复杂度为 \( \theta(n^2) \)[^1]。
---
#### 方法二:\( \theta(n\log n) \) 时间复杂度(分治法)
利用分治策略将原数组分为左半部分、右半部分以及跨越中间的部分,递归求解每种情况下的最大子数组,并返回三者中的最大值。
```cpp
#include <climits>
struct Result {
int sum;
int low;
int high;
};
Result findMaxCrossingSubarray(const vector<int>& nums, int low, int mid, int high) {
int leftSum = INT_MIN;
int total = 0;
int maxLeft = mid;
for (int i = mid; i >= low; --i) {
total += nums[i];
if (total > leftSum) {
leftSum = total;
maxLeft = i;
}
}
int rightSum = INT_MIN;
total = 0;
int maxRight = mid + 1;
for (int j = mid + 1; j <= high; ++j) {
total += nums[j];
if (total > rightSum) {
rightSum = total;
maxRight = j;
}
}
return {leftSum + rightSum, maxLeft, maxRight};
}
Result findMaximumSubarray(const vector<int>& nums, int low, int high) {
if (high == low) {
return {nums[low], low, high};
} else {
int mid = (low + high) / 2;
auto leftResult = findMaximumSubarray(nums, low, mid);
auto rightResult = findMaximumSubarray(nums, mid + 1, high);
auto crossResult = findMaxCrossingSubarray(nums, low, mid, high);
if (leftResult.sum >= rightResult.sum && leftResult.sum >= crossResult.sum) {
return leftResult;
} else if (rightResult.sum >= leftResult.sum && rightResult.sum >= crossResult.sum) {
return rightResult;
} else {
return crossResult;
}
}
}
```
上述分治法的时间复杂度为 \( \theta(n\log n) \)[^2]。
---
#### 方法三:\( \theta(n) \) 时间复杂度(Kadane's Algorithm)
这是一种动态规划的方法,在一次线性扫描中维护当前子数组的最大和以及全局最大和。
```cpp
pair<int, pair<int, int>> kadanesAlgorithm(const vector<int>& nums) {
int maxSoFar = INT_MIN;
int maxEndingHere = 0;
int start = 0, s = 0, end = 0;
for (int i = 0; i < nums.size(); ++i) {
maxEndingHere += nums[i];
if (maxSoFar < maxEndingHere) {
maxSoFar = maxEndingHere;
start = s;
end = i;
}
if (maxEndingHere < 0) {
maxEndingHere = 0;
s = i + 1;
}
}
return {maxSoFar, {start, end}};
}
```
这种方法仅需单次遍历即可完成任务,因此时间复杂度为 \( \theta(n) \)[^3]。
---
#### 随机生成数据并测试运行时间对比
为了比较这三种算法的实际性能表现,可以通过随机生成不同规模的数据来进行实验:
```cpp
#include <chrono>
#include <random>
#include <iomanip>
void testPerformance() {
const int MAX_SIZE = 10000;
default_random_engine generator(time(nullptr));
uniform_int_distribution<int> distribution(-100, 100); // Random values between -100 and 100
cout << fixed << setprecision(6) << "Size\tN^2 Time(s)\tNLogN Time(s)\tLinear Time(s)" << endl;
for (int size = 100; size <= MAX_SIZE; size *= 2) {
vector<int> data(size);
generate(data.begin(), data.end(), [&]() { return distribution(generator); });
// Quadratic Method Timing
auto startTime = chrono::steady_clock::now();
maxSubArrayQuadratic(data);
auto endTime = chrono::steady_clock::now();
double quadraticTime = chrono::duration_cast<chrono::microseconds>(endTime - startTime).count() / 1e6;
// Divide-and-Conquer Method Timing
startTime = chrono::steady_clock::now();
findMaximumSubarray(data, 0, size - 1);
endTime = chrono::steady_clock::now();
double divideAndConquerTime = chrono::duration_cast<chrono::microseconds>(endTime - startTime).count() / 1e6;
// Kadane’s Algorithm Timing
startTime = chrono::steady_clock::now();
kadanesAlgorithm(data);
endTime = chrono::steady_clock::now();
double linearTime = chrono::duration_cast<chrono::microseconds>(endTime - startTime).count() / 1e6;
cout << size << "\t" << quadraticTime << "\t" << divideAndConquerTime << "\t" << linearTime << endl;
}
}
```
以上程序会打印出随着输入大小增加时各算法所需耗时的变化趋势。
---
阅读全文
相关推荐


















