There are two ways to solve the problem of largest sub array:
1: divide-and-conquer method
2: linear search method
Now let me introduce them one by one.
1: divide-and-conquer method
The core idea of it is to divide the array to two sub arrays, you need to find out the largest sub array from the above two sub arrays, and the most important thing is you can not ignore the middle sub array cross the middle node. So at each level, you can find out 3 sub largest sub arrays, the left one, the right one and the middle one cross the middle node, and then choose the max one as the largest sub array of the above level. Recursively divide the sub array of each level until each sub array only has one node that is the leaf node.
The detail steps of this algorithm are as follow:
1).find out the middle element's position named m.
2).divide the array to tow sub arrays, the left one is from 0 until m, the right one is from m+1 until the end of the array.
3).make each sub array as the parameter and call the method itself recursively.
4).find out the middle largest sub array crosses the middle node which position is m.
5).compare the three sub array, find out the largest one
The recursion is such that:
T(n) = O(1)for n = 1
T(n) = 2(T(n/2))+O(n) for all n > 1
So the complexity of T(n) is O(nlgn).
The following is the implement of divide-and conquer method by java.
private int[] findLargestSubArray1 (int[] array, int l, int r){
if(l >= r){
return array;
}else{
int m = (l+r)/2;
int[] l_result =findLargestSubArray1(array,l, m);
int[] r_result = findLargestSubArray1(array,m+1,r);
int[] m_result =middleLargetSubArray(array,l,r,m);
if(l_result[2] > r_result[2]&& l_result[2] > m_result[2]){
return l_result;
}else if(r_result[2] >l_result[2] && r_result[2] > m_result[2]){
return r_result;
}else{
return m_result;
}
}
}
private int[] middleLargetSubArray(int[] array, int l, int r,int m){
int l_max = 0;
int r_max = 0;
int sum = 0;
int l_el = 0;
int r_el = 0;
for(int i = m;i >= 0;i--){
sum = sum + array[i];
if(sum > l_max){
l_max = sum;
l_el = i;
}
}
sum = 0;
for(int i = m+1;i < r;i++){
sum = sum + array[i];
if(sum > r_max){
r_max = sum;
r_el = i;
}
}
return new int[] {l_el,r_el,l_max+r_max};
}
2: linear search method
The core idea is iterate the array from left to right and sum them, and cache the max sum value and the current subarray after each calculation. If the result is larger than the cached max sum value then replace max sum value with the result. If the result is less than 0,then abandon the cached sub array, make next element as the first element of the new sub array and start the new calculation.
1).iterate the array from left to right.
2).sum the elements that has been iterated.
3).compare the result with the max sum value had been cached, and then to choose the larger one to replace the max sum value.
4).if you find the result has less than 0,you need to abandon the sub array you cache now. from the next element, to findthe new sum array.
The complexity is O(n).
The following is the implement of the linear search by java.
private int[] findLargestSubArray2 (int[] array){
int new_l_el = 0;
int l_el = 0;
int r_el = 0;
int sum = 0;
int maxSum = 0;
for(int i = 0; i < array.length;i++){
sum = sum + array[i];
if(sum > maxSum){
maxSum = sum;
l_el = new_l_el;
r_el = i;
}else if(sum <= 0){
sum = 0;
new_l_el = i+1;
}
}
return new int[] {l_el,r_el,maxSum};
}