分治策略---求最大子数组

只有当数组中包含负数时,最大子数组问题才有意义。如果所有元素都是非负的,最大子数组问题没有任何意义,因为整个数组和肯定是最大的

 1 public class FindMaxSubArrayDemo {
 2     public static void main(String[] args) {
 3         int[] arr = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
 4         int[] result_arr = findMaximumSubarray(arr, 0, arr.length - 1);
 5         for (int i = 0; i < result_arr.length; i++) {
 6             System.out.println(result_arr[i]);
 7         }
 8     }
 9 /*
10 最大数组问题:使用分治策略
11     分析:1.要将大数组划分为两个规模尽量相等的子数组,也就是找到大数组的中央位置mid,
12          2.求解两个子数组A[low,mid]和A[mid+1,high]
13          3,那么所求的最大数组A[i,j]就只用三种情况
14             * 第一种情况:完全位于A[low,mid],因此low <= i <= j <= mid;
15             * 第二种情况:完全位于A[mid+1,high],因此 mid+1 <= i <= j <= high;
16             * 第三种情况:跨越了中点,因此low <= i <= mid j <= high;
17          4.可以递归第一种和第二种情况的最大子数组问题,因为两个子问题仍然是最大数组问题,只是规模更小
18          5.因此,只要寻找跨越中点的最大子数组
19          6.最后进行三者比较选取最大值的问题。
20  */
21     public static int[] findMaxCrossingSubArray(int[] arr, int low, int mid, int high) {//找出跨越中点最大子数组的方法
22         int left_sum = arr[low];//存储左半部的和
23         int sum = 0; //存储元素和,来分别与左右半部的和进行比较
24         int right_sum = arr[high]; //存取右半部的和
25         int max_left = 0; //存取最左边的角标
26         int max_right = 0;//存取最右边的角标
27         int[] result_arr = new int[3];
28         for (int i = mid; i >= low; i--) {
29             sum = sum + arr[i];
30             if (sum > left_sum) {
31                 left_sum = sum;
32                 max_left = i;
33             }
34         }
35         sum = 0;
36         for (int i = mid + 1; i <= high; i++) {
37             sum = sum + arr[i];
38             if (sum > right_sum) {
39                 right_sum = sum;
40                 max_right = i;
41             }
42         }
43         result_arr[0] = max_left;
44         result_arr[1] = max_right;
45         result_arr[2] = left_sum + right_sum;
46         return result_arr;
47     }
48 
49     public static int[] findMaximumSubarray(int[] arr, int low, int high) {
50         int[] result_arr = new int[3];
51         if (high == low) {  //base case: only one element
52             result_arr[0] = low;
53             result_arr[1] = high;
54             result_arr[2] = arr[low];
55             return result_arr;
56         } else {
57             int mid = (low + high) / 2;
58             int[] left_result_arr = findMaximumSubarray(arr, low, mid); //第一种情况
59             int[] right_result_arr = findMaximumSubarray(arr, mid + 1, high); //第二种情况
60             int[] cross_result_arr = findMaxCrossingSubArray(arr, low, mid, high); //第三种情况
61             if (left_result_arr[2] >= right_result_arr[2] && left_result_arr[2] >= cross_result_arr[2]) {
62                 return left_result_arr;
63             } else if (right_result_arr[2] >= left_result_arr[2] && right_result_arr[2] >= cross_result_arr[2]) {
64                 return right_result_arr;
65             } else {
66                 return cross_result_arr;
67             }
68         }
69     }
70 }

 

posted @ 2018-08-12 15:07  Joe0428  阅读(259)  评论(0编辑  收藏  举报