Problem: Find the array A [l..r] each element in the sum of the maximum continuous non-empty array. We call such an array called the largest sub-array.
This article presents three solutions: to solve the violence, divide and conquer, dynamic programming. Time complexity in descending order.
In order to facilitate spread function results, we define a structure to store the maximum subarray elements, i.e. the sub-array subscript and bounds of the original array and the corresponding.
typedef struct subArray {
int l; //子数组的左边界
int r; //子数组的右边界
int sum; //子数组每一项的和
} SUB_ARRAY;
Method One: Solution of violence -
Obviously, you need two for loop to loop through all of the sub-array of the original array, time complexity is very high.
This bad idea, not the code.
Method Two: Divide and Conquer -
1, points (Divide)
We are looking for an array a [l, r] is the maximum sub-arrays, the array we can be decomposed into two sub-arrays of equal size as possible . Found i.e. mid center position of the array, then divided into a left sub-array a [l, mid] and the right sub-array a [mid + 1, r] be considered.
2, treatment (Conquer)
Then a [l, r] of the present embodiment has three sub-arrays, sub-arrays in the left, in the right sub-arrays, the mid-point across the array. We should look at the three biggest range of sub-arrays, both front we can recursively called to solve , because the problem is still seeking two sub-sub-arrays largest general question, but smaller scale. Then find the maximum span midpoint sub-arrays, we can write a single function, in O (n) time, to both sides from the mid traverse can.
The complete code is as follows:
// Created by A on 2020/3/5.
#include <climits>
typedef struct subArray {
int l; //子数组的左边界
int r; //子数组的右边界
int sum; //子数组每一项的和
} SUB_ARRAY;
/* 在数组a[l,r]内找到包含m下标位置的最大子数组 */
SUB_ARRAY FindMaxCrossingSubarray(int a[], int l, int m, int r) {
/* 计算从m出发的左半边数组的最大子数组 */
int leftMax = INT_MIN, leftIndex, t = 0;
for (int i = m; i >= l; i--) {
t += a[i];
if (t > leftMax) {
leftIndex = i; //最大位置对应的下标
leftMax = t; //最大和
}
}
t = 0;
/* 计算从m + 1出发的右半边数组的最大子数组 */
int rightMax = INT_MIN, rightIndex;
for (int i = m + 1; i <= r; i++) {
t += a[i];
if (t > rightMax) {
rightIndex = i; //最大位置对应的下标
rightMax = t; //最大和
}
}
SUB_ARRAY ans;
ans.l = leftIndex;
ans.r = rightIndex;
ans.sum = leftMax + rightMax;
return ans;
}
/* 在数组a[l,r]内找到最大子数组(非空!) */
SUB_ARRAY FindMaxSubarray(int a[], int l, int r) {
/* 递归的终点,数组只有一个元素 */
if(l == r) {
SUB_ARRAY ans;
ans.l = ans.r = l;
ans.sum = a[l];
return ans; //直接将原数组作为最大子数组返回
}
int mid = (l + r) / 2; //中间位置
SUB_ARRAY leftAns = FindMaxSubarray(a, l, mid); //递归地求mid左侧的最大子数组
SUB_ARRAY rightAns = FindMaxSubarray(a, mid + 1, r); //递归地求mid右侧地最大子数组
SUB_ARRAY midAns = FindMaxCrossingSubarray(a, l, mid, r); //求包含mid地最大子数组
/* 返回三者中和最大的 */
if(leftAns.sum > midAns.sum && leftAns.sum > rightAns.sum)
return leftAns;
else if(midAns.sum > rightAns.sum)
return midAns;
else
return rightAns;
}
Method three: Dynamic Programming -
1, the algorithm description
This is a great non-recursive method of linear time complexity:
If the maximum subarray known array a [0..j], then a [0..j + 1] is the largest sub-array is one of the following two situations:
- Subarray is the maximum array a [0..j]: Not including the first item j + 1
- J + 1 includes a first item: a [k..j + 1] (where 0 <= k <= j + 1)
2, algorithm
Scratch loop through the array a, traverse to the index subscript i: a cur recording a [0..i] within comprises i-th item largest sub-arrays, with the maximum recording sub ans a [0..i] in array. (Explained below when using cur (), ANS () represent two variables in brackets traversed subscript index represented in the traverse to a position corresponding to the cur ans.)
If known cur (i) and ans (i), then continue to traverse the next element:
- According to the definition of cur, cur (I +. 1) should be cur (i) + a [i + 1] and a [i 1 +] larger values
- The algorithm described in said: ANS (I +. 1) should be a larger value cur (i + 1) and ans (i) in . Then traverse completed ans is the answer.
The following is a specific algorithm for drawing a traverse:
Understand the algorithm, the code is very simple:
#include <climits>
typedef struct subArray {
int l; //子数组的左边界
int r; //子数组的右边界
int sum; //子数组每一项的和
} SUB_ARRAY;
/* 在数组a[l,r]内找到最大子数组(非空!) */
SUB_ARRAY FindMaxSubarray1(int a[], int l, int r) {
int ans = INT_MIN, cur = INT_MIN;
int curLeft, leftIndex, rightIndex; //记录cur对应的子数组左下标、记录ans对应的子数组左右下标
for (int i = l; i <= r; i++) {
/* 找到a[ 0..i ]内包含第i项的最大子数组 */
if (cur + a[i] >= a[i])
cur += a[i];
else {
cur = a[i];
curLeft = i;
}
/* 更新a[ 0..i ]内的最大子数组 */
if (cur > ans) {
ans = cur;
leftIndex = curLeft;
rightIndex = i;
}
}
/* 返回答案 */
SUB_ARRAY result;
result.l = leftIndex;
result.r = rightIndex;
result.sum = ans;
return result;
}
end
No personal welcome attention to the public " chicken wings Programming" , here is a serious and well-behaved code agricultural one.
---- do the most well-behaved blog er, do the most solid programmer ----
Aims to carefully write each article, usually aggregated into notes will push updates -