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

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

 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 }

原文地址:https://www.cnblogs.com/Joe-666/p/9463085.html

时间: 2024-09-30 20:50:32

分治策略---求最大子数组的相关文章

分治策略之最大子数组问题

从股票买卖问题转换成为一个求最大子数组问题 天 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 价格 100 113 110 85 105 102 86 63 81 101 94 106 101 79 94 90 97 变化 13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7 暴力求解所花费的时间是O(n^2) 采用分治技术来求解最大子数组问题,假定要求的数组为A[low..high]的最大子数组. 将子数组划分

一维数组头尾相连求最大子数组

题目: 返回一个整数数组中最大子数组的和. 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 求所有子数组的和的最大值.要求时间复杂度为O(n). 1. 设计思想: 因为已经写过了一维数组的求最大子数组程序.所以只是在原程序上进行修改.首先产生随机数数组,然后进行计算,因为要求时间复杂度

二维数组求最大子数组

设计思路: 首先定义产生二维数组,定义可输入二维数组行和列,各位数随机产生: 然后进行最大子数组的求和比较,从每行的第一个数为子数组的起点开始进行不同的子数组遍历比较,只存放最大的子数组,以及记录最大子数组的位置,从第一个数开始每行每列进行求和比较,以求得最大子数组的值,以及最大子数组所包含的数: 最后进行结果的输出与验证. 代码: 法一: package zishuzu; import java.util.*; public class zuixiaozishuzu { public stat

一维数组求最大子数组(解决溢出问题)

一.题目要求 题目:返回一个整数数组中最大子数组的和. 要求: 要求程序必须能处理1000 个元素: 每个元素是int32 类型的: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 二.设计思想 程序在宏里面定义出了数组长度的大小,在长度超过100万的时候程序直接崩溃,其实这并不是因为结果太大导致的数值溢出,而是因为内存溢出,我们的数组是定义在程序内部的,属于局部变量,存放位置在栈上

结对开发--四实现循环二维数组求最大子数组的和

一.实现思路 再上一个实验基础上加上环,我们实现环的思想是每一列依次向此替换,直至替换出能出现的所有的二维数组,再用上一个求最大子数组的方法全部实现 二.实验代码 package com.minirisoft; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.Scanner; public class HuanTwoArray { public stat

课堂作业:首尾相连求最大子数组

1.设计思想 先将数组环拆解补在原来数组后面,再依次找子数组并相加,更新最大值,并需要将开始的负数舍去从正数开始算起,单独讨论全负情况. 2.源程序 package zishuzu; import java.util.Scanner; public class zsz { public static void main(String[] args) { System.out.println("请输入数字个数:"); Scanner in=new Scanner(System.in);

数组问题之求最大子数组问题(一)

结束了 四则运算的所有内容 这次老师布置了 数组问题 求最大子数组的问题 课堂上 老师就已经提供了数种方案 并提出了时间复杂度的要求 于是和我的搭档找到了认为最为简便的算法 过程中和小于0,那么和最大的子数组不会包含前面子数组,之后将和归0,从下个元素重新开始计算 于之前的实验 理清思路 代码实现不算太难 代码如下 1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 int i,num; 7 cout <<

结对——二维数组首尾相连求最大子数组和

一.题目与要求 题目.返回一个二维整数数组中最大子数组的和 要求.1.输入一个二维整形数组,数组里有正数也有负数. 2.二维数组首尾相接,象个一条首尾相接带子一样. 3.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和 二.设计思路 在上一次的以为循环数组的基础上,和二维数组求最大子数组相结合,将功能合并,完成题目要求. 第一步.将每一行的数组作为循环数组求最大子数组 第二步.通过枚举的方式,将每一种情况的和存入到新建二维数组中 第三部.通过逐列计算最大子数组的方法求所有子矩阵的最

循环一维数组求最大子数组

题目: 随机出一个一维数组,设该数组为循环数组,求其最大小子数组. 一.设计思路 求最大子数组,就求出最大的连续正子数组. 将数组分为全负和有非负值两种情况.全负求出最大值即可. 在有非负值的情况下,先判断该随机数组的首尾是否相连,即首尾是否都大于等于零.如果首尾相连,则将该一维数组分为首.中.尾三部分,先求出首尾和S1,再求中间最大连续正子数组和S,令S1和S与maxS相比较,求出最大子数组:如果首尾不相连,则直接借鉴前一种情况中部的算法,求最大正子数组S. 二.源代码 1 //刘双渤,刘洪阳