最大子数组问题及C语言实现

来源:互联网 发布:中国电信cn2网络 编辑:程序博客网 时间:2024/05/01 11:57


对于一个连续的数组a[n],要求连续子数组,使得该子数组的和最大。比如数组{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7},最大子数组为{18,20,-7,12},和为32。


方法一:穷举法。即将任取数组中的两个元素,算出两者之间(包括这两个元素本身)所有元素之和。穷举所有组合,比较得到最大值。该方法复杂度为n的三次方。

#include <stdio.h>#include <limits.h>int sort(int *,int,int);main(){int a[16] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};printf("%d\n",sort(a,0,15));}int sort(int *a,int low,int high){int i,j,k,sum,max_sum;max_sum = INT_MIN;for (i = low;i <= high;i++) {for (j = low+1;j <= high;j++) {sum = 0;for (k = i;k <= j;k++) {sum += a[k];}if (sum > max_sum)max_sum = sum;}}return max_sum;}

方法二:递归法。以数组中间元素为分界,将整个数组分为左边的数组和右边数组。那么最大子数组有三种情况,分别是完全位于左数组,完全位于右数组以及横跨中间元素的数组。分别对左右数组进行递归,得到最终答案。该方法复杂度为nlgn。

#include <stdio.h>#include <limits.h>int find_max_crossing_subarray(int *,int,int,int);//横跨左右数组的最大子数组int find_maximum_subarray(int *,int,int);//返回最大子数组的和main(){int a[16] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};printf("%d\n",find_maximum_subarray(a,0,15));}int find_max_crossing_subarray(int *a,int low,int mid,int high){int left_sum = INT_MIN;int right_sum = INT_MIN;int sum,i;sum = 0;//处理左数组for (i = mid;i >= 0;i--) {sum += a[i];if (sum > left_sum) {left_sum = sum;}}sum = 0;//处理右数组for (i = mid+1;i <= high;i++) {sum += a[i];if (sum > right_sum) {right_sum = sum;}}return left_sum + right_sum;}int find_maximum_subarray(int *a,int low,int high){int mid;int max_sum,max_sum1,max_sum2;max_sum = max_sum1 = max_sum2 = INT_MIN;if (high == low) {//元素数量为1的情况return a[low];} else {mid = (low + high) / 2;max_sum1 = find_maximum_subarray(a,low,mid);max_sum2 = find_maximum_subarray(a,mid+1,high);max_sum = find_max_crossing_subarray(a,low,mid,high);if (max_sum >= max_sum1 && max_sum >= max_sum2)return max_sum;else if (max_sum1 >= max_sum && max_sum1 >= max_sum2)return max_sum1;elsereturn max_sum2;}}

方法三:当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。因此,当和为负数时,应该清零,并重新开始寻找最大子数组,当数组元素全为负数时,找到最大元素即可。

#include <stdio.h>#include <limits.h>int line_sort(int *,int,int);main(){int a[16] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};printf("%d\n",line_sort(a,0,15));}int line_sort(int *a,int low,int high){int i,sum,max_sum;int index_start,index_end;sum = 0;max_sum = INT_MIN;for (i = low;i <= high;i++) {sum += a[i];if (sum < 0) {sum = 0;index_start = i + 1;}if (sum > max_sum) {max_sum = sum;index_end = i;}}if (max_sum == 0) {max_sum = a[low];for (i = low + 1;i <= high;i++) {if (max_sum < a[i]) {max_sum = a[i];index_start = index_end = i;}}}printf("index_start:%d, index_end:%d \n",index_start,index_end);return max_sum;}



0 0
原创粉丝点击