• 最大子数组问题(求连续子数组的最大和)


    在<算法导论>第四章分治策略(Divider and Conquer)4.1节提出了最大子数组问题。其转化就是求数组a={1, -2, 3, 10, -4, 7 , 2, -5}中连续子数组的最大和。

    对于这个问题,很容想到一种暴力求解的方法:简单地尝试对所有可能的的组合进行求和。对数组为n存在n*(n-1)/2中组合,然后对每个组合进行求和。即三个for循环遍历,求出数组中每一个子数组的和,最终求出这些子数组的最大的一个值。记Sum[i,...,j]为数组a中第i个元素到第j个元素的和(其中0<=i<=j<n),遍历所有可能的Sum[i,...,j],那么时间复杂度(最大运行时间running Time)为Ο(n^3)。

     1 package algorithms;
     2 
     3 /**
     4  * @author public
     5  *本段代码参考编程之美
     6  */
     7 public class MaxSubarraySum {
     8     
     9     static int[] a = {1, -2, 3, 10, -4, 7, 2, -5};
    10     static int sum;
    11     static int maxSum = 0;
    12     public static void main(String[] args) {
    13         // TODO Auto-generated method stub
    14         for (int i = 0; i < a.length; i++) {
    15             for (int j = i; j < a.length; j++) {
    16                 for (int k = i; k <= j; k++) {
    17                     sum += a[k];
    18                 }
    19                 if (sum > maxSum) {
    20                     maxSum = sum;                    
    21                 }
    22                 sum = 0;//无论是sum>maxSum还是sum<=maxSum都要对sum进行清零操作
    23             }
    24         }
    25         
    26         System.out.println("maxSum="+maxSum);
    27         
    28     }
    29 
    30 }

    运行结果:

    maxSum=18 

    在算法导论4.1-5习题提到如下思想:最大字数组问题设计一个非递归的、线性时间的算法。从数组的左边界开始,由左到右处理,记录到目前为止已经处理过的最大字数组。若已知a[1,...,j]的最大子数组,基于如下性质将解扩展为a[1,...,j+1]的最大子数组:a[1,...,j+1]的最大子数组要么是a[1,...,j]的最大子数组,要么是某个子数组a[i,...,j+1](1≤i≤j+1)。在已知a[1,...,j]的最大子数组的情况下,可以在线性时间内找出形如a[i,...,j+1]的最大子数组

    实现方法:

     1 package algorithms;
     2 
     3 public class FindMaxSubarray {
     4     
     5     static int[] array = {1, -2, 3, 10, -4, 7, 2, -5};
     6 
     7     public static void main(String[] args) {
     8         MaxSum(array);
     9     }
    10 
    11     private static void MaxSum(int[] arraytmp) {
    12         // TODO Auto-generated method stub
    13         if (arraytmp==null) {
    14             return;
    15         }
    16         
    17         int curSum = 0, maxSum = 0;
    18         
    19         int indexStart = 0, indexEnd = 0;    //初始化字数组最大和下标
    20         
    21         for (int j = 0; j < arraytmp.length; j++) {
    22             curSum += arraytmp[j];//累加
    23             
    24             if (curSum < 0) {  //当前和小于0,重置为0
    25                 curSum = 0;
    26                 indexStart = j+1;//调整字数组最大和的开始下标
    27             }
    28             
    29             if (curSum > maxSum) {    //当前和大于最大和,则重置最大和
    30                 maxSum = curSum;
    31                 indexEnd = j;    //调整字数组最大和的结束下标
    32             }
    33             
    34         }
    35         
    36         if (maxSum == 0) {        //最大和依然为0,说明数组中所有元素都为负值
    37             maxSum = arraytmp[0];
    38             indexStart = indexEnd = 0;        //初始化子数组最大和下标
    39             for (int j = 0; j < arraytmp.length; j++) {
    40                 if (arraytmp[j] > maxSum) {
    41                     maxSum =arraytmp[j];
    42                     indexEnd = indexStart = j;//调整子数组最大和下标
    43                 }
    44             }
    45         }
    46         
    47         for (int i = indexStart; i <= indexEnd; i++) {
    48             System.out.print(arraytmp[i]+" ");//输出最大和的子数组
    49         }
    50         System.out.println();
    51         System.out.println("maxSum="+maxSum);//输出子数组最大和
    52     }
    53 
    54 }

    运行结果:

    3 10 -4 7 2 
    maxSum=18
  • 相关阅读:
    调用Android自带日历功能
    android使用全局变量传递数据
    安卓高手之路之java层Binder
    无刷新实时获得数据
    Android画图之抗锯齿
    android 定时器的实现
    将apk文件添加到Android模拟器(AVD)中运行
    Android 屏幕自适应方向尺寸
    经常用得到的安卓数据库基类
    android系统特效详解和修改方法
  • 原文地址:https://www.cnblogs.com/chuji1988/p/4179662.html
Copyright © 2020-2023  润新知