(7)连续子数组问题

来源:互联网 发布:10nba总决赛第七场数据 编辑:程序博客网 时间:2024/06/10 03:06
#include <iostream>using namespace std;/*输入一个整形数组,数组里有正数也有负数。 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18。1.三重循环 n*32.两重循环 n*23.分治法   nlogn4.动态规划 n*/void TestMaxSumOfSequence();// 三重循环void MaxSumOfSequence(int *arr, unsigned n, int &best, unsigned &bestStart, unsigned &bestEnd);// 两重循环void MaxSumOfSequence_2(int *arr, unsigned n, int &best, unsigned &bestStart, unsigned &bestEnd);// 分治法void MaxSumOfSequence_3(int *arr, unsigned start, unsigned end, int &best, unsigned &bestStart, unsigned &bestEnd);// 以middle为轴,向左、向右计算,求出最大void MiddleSum(int *arr, unsigned start, unsigned end, int middle, int &best, unsigned &bestStart, unsigned &bestEnd);// 动态规划/*sum[i]:前i个且包含i的最大和sum[i] = max{0, sum[i - 1] + a[i]}*/void MaxSumOfSequence_4(int *arr, unsigned n, int &best, unsigned &bestStart, unsigned &bestEnd);// 二维数组// 乘积列:如果sum>1..,但是正负交替呢?

#include <limits.h>#include "7_MaxSumOfSequence.h"void TestMaxSumOfSequence(){int arr[] = {1, -2, 3, 10, -4, 7, 2};//int best = 0x80000000;int best = 0x1<<31;unsigned left, right;MaxSumOfSequence_4(arr, 7, best, left, right);cout << best << endl;cout << left << " -> " << right << endl;for (unsigned i = left; i <= right; ++i){cout << arr[i] << " ";}}// 三重循环void MaxSumOfSequence(int *arr, unsigned n, int &best, unsigned &bestStart, unsigned &bestEnd){for (unsigned i = 0; i < n; ++i){for (unsigned j = i; j < n; ++j){int sum = 0;for (unsigned k = i; k <= j; ++k){sum += arr[k];}if (sum > best){best = sum;bestStart = i;bestEnd = j;}}}}void MaxSumOfSequence_2(int *arr, unsigned n, int &best, unsigned &bestStart, unsigned &bestEnd){for (unsigned i = 0; i < n; ++i){int sum = 0;for (unsigned j = i; j < n; ++j){sum += arr[j];if (sum > best){best = sum;bestStart = i;bestEnd = j;}}}}// 包含左边、右边、中间void MaxSumOfSequence_3(int *arr, unsigned start, unsigned end, int &best, unsigned &bestStart, unsigned &bestEnd){if (end == start){if (arr[start] > 0){best = arr[start];}else{best = 0;}bestStart = bestEnd = start;}unsigned middle = (start + end) / 2;// middle 放入左边int bestLeft = -INT_MAX;unsigned bestLeftStart = 0;unsigned bestLeftEnd = 0;MaxSumOfSequence_3(arr, start, middle, bestLeft, bestLeftStart, bestLeftEnd);int bestRight = -INT_MAX;unsigned bestRightStart = 0;unsigned bestRightEnd = 0;MaxSumOfSequence_3(arr, middle + 1, end, bestRight, bestRightStart, bestRightEnd);if (bestRight > bestLeft){best = bestRight;bestStart = bestRightStart;bestEnd = bestRightEnd;} else{best = bestLeft;bestStart = bestLeftStart;bestEnd = bestLeftEnd;}unsigned middleStart;unsigned middleEnd;int middleBest;MiddleSum(arr, start, end, middle, middleBest, middleStart, middleEnd);if (middleBest > best){best = middleBest;bestStart = middleStart;bestEnd = middleEnd;}}void MiddleSum(int *arr, unsigned start, unsigned end, int middle, int &best, unsigned &bestStart, unsigned &bestEnd){best = 0;int sum = 0;bestStart = middle;bestEnd = middle;// 向左时包括middleunsigned toLeft = middle;int leftSum = 0;int leftMaxSum = 0;while (toLeft >= start){leftSum += arr[toLeft];if (leftSum > leftMaxSum){leftMaxSum = leftSum;bestStart = toLeft;}}unsigned toRight = middle + 1;int rightSum = 0;int rightMaxSum = 0;while (toRight <= end){rightSum += arr[toRight];if (rightSum > rightMaxSum){rightMaxSum = rightSum;bestEnd = toRight;}}best = leftMaxSum + rightMaxSum;}void MaxSumOfSequence_4(int *arr, unsigned n, int &best, unsigned &bestStart, unsigned &bestEnd){int sum = 0;int curStart = 0;int curEnd = 0;for (unsigned i = 0; i < n; ++i){sum += arr[i];curEnd = i;if (sum > best){best = sum;bestStart = curStart;bestEnd = curEnd;}if (sum < 0){sum = 0;curStart = i + 1;curEnd = i + 1;}}}