连续项的最大和问题
(1)暴力求解 时间复杂度 O(n^2)
(2)分治求解 时间复杂度 O(nlogn)
(3) 线性求解 时间复杂度 O(n)
C#代码
using System;
using System.Collections.Generic;namespace dataLearn
{class Program{static void Main(string[] args){List<int> list1 = new List<int> { -2, 4, -1, 3, 5, -6, 1, 2 };List<int> list2 = new List<int> { 4, 1, -3, 7, -1, -5, 3, -2 };List<int> list3 = new List<int> { -1, 6, 3, -4, -5, 8, -1, 7 };var max1 = MaxSumViolence(list1, 0, list1.Count - 1);Console.WriteLine(max1.start + " " + max1.end + " " + max1.value);var max2 = MaxSumViolence(list2, 0, list2.Count - 1);Console.WriteLine(max2.start + " " + max2.end + " " + max2.value);var max3 = MaxSumViolence(list3, 0, list3.Count - 1);Console.WriteLine(max3.start + " " + max3.end + " " + max3.value);var max4 = MaxSum(list1, 0, list1.Count - 1);Console.WriteLine(max4.start + " " + max4.end + " " + max4.value);var max5 = MaxSum(list2, 0, list2.Count - 1);Console.WriteLine(max5.start + " " + max5.end + " " + max5.value);var max6 = MaxSum(list3, 0, list3.Count - 1);Console.WriteLine(max6.start + " " + max6.end + " " + max6.value);}static (int start,int end,float value) MaxSumViolence(List<int> list ,int start,int end){int s = start, e = end;int max = list[start];for(int i=start;i<end+1;i++){int total = list[i];for(int j=i+1;j<end+1;j++){total += list[j];if(total>max){max = total;s = i;e = j;}}}return (s, e, max);}static (int start,int end,float value) MaxSum(List<int> list,int start,int end){if (start != end){int middle = (start + end) / 2;var leftMax = MaxSum(list, start, middle);var rightMax = MaxSum(list, middle + 1, end);var max = leftMax.value > rightMax.value ? leftMax : rightMax;int l = middle, r = middle + 1;float lvalue = list[middle];float rvalue = list[middle + 1];float temp = lvalue;for (int i = middle - 1; i >= start; i--){temp += list[i];if (temp > lvalue){l = i;lvalue = temp;}}temp = rvalue;for (int i = middle + 2; i <= end; i++){temp += list[i];if (temp > rvalue){r = end;rvalue = temp;}}if (max.value < lvalue + rvalue){return (l, r, lvalue + rvalue);}else return max;}elsereturn (start, start, list[start]);}}
}
c++ 代码
数据结构
#include <iostream>
class SubarrayResult{
public:int value;int left;int right;
public:SubarrayResult(int value,int left,int right):value(value),left(left),right(right){};SubarrayResult(){};friend std::ostream & operator<<(std::ostream &os,const SubarrayResult &result){return os<<"value:"<<result.value<<",left:"<<result.left<<",right:"<<result.right;}bool operator>=(const SubarrayResult & other){return this->value>= other.value;}
};
暴力求解法:时间复杂的O(n^2)
SubarrayResult brute_force_find_maximum_subarray(int *arr,int start,int end)
{int max_sum = INT_MIN;int sum = 0;int low = 0;int high = 0;for (int i = start; i < end+1; ++i) {sum = 0;for (int j = i; j < end+1 ; ++j) {sum += arr[j];if(sum>max_sum){max_sum = sum;low = i;high = j;}}}return SubarrayResult(max_sum,low,high);
}
分治递归求解法:
T(n)=2T(n/2)+θ(n)
时间复杂度(nlgn)
SubarrayResult find_crossing_subarray(int *arr,int start,int end ,int middle);SubarrayResult find_maximum_subarray(int *arr,int start,int end)
{if(start == end)return SubarrayResult(arr[start],start,end);else{int middle = (start + end)/2;SubarrayResult left_result = find_maximum_subarray(arr,start,middle);SubarrayResult right_result = find_maximum_subarray(arr,middle+1,end);SubarrayResult cross_result = find_crossing_subarray(arr,start,end,middle);if(left_result >= right_result && left_result >= cross_result)return left_result;else if(right_result >= left_result && right_result >= cross_result)return right_result;else return cross_result;}
}SubarrayResult find_crossing_subarray(int *arr,int start,int end, int middle)
{int left_sum = INT_MIN,right_sum = INT_MIN;int sum = 0,max_left = 0, max_right = 0;for (int i = middle; i >= start ; i--) {sum += arr[i];if(sum>left_sum){left_sum = sum;max_left = i;}}sum = 0;for (int i = middle + 1; i < end+1; ++i) {sum += arr[i];if(sum>right_sum){right_sum = sum;max_right = i;}}return SubarrayResult(left_sum+right_sum,max_left,max_right);
}
线性求解法:
时间复杂度O(n)
SubarrayResult iterative_find_maximum_subarray(int *arr,int start,int end)
{int left = 0,right = 0,current_low = 0,current_high = 0;int sum = INT_MIN ,max_sum = INT_MIN;for (int i = start; i < end+1; ++i) {current_high = i;if(sum > 0){sum += arr[i];}else{current_low = i;sum = arr[i];}if(sum > max_sum){max_sum = sum;left = current_low;right = current_high;}}return SubarrayResult(max_sum,left,right);
}