求一个整形数组最大子序列的和

Posted optor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求一个整形数组最大子序列的和相关的知识,希望对你有一定的参考价值。

这道题目是昨天上午在猫眼面试时遇到的,总感觉似曾相识,但是却有想不出在哪见过。当然了,这道题最终我是没有解答出来的,这会就再好好思考下怎么解决这个问题吧!
算法战五渣的我思考了一会还是没思路就不浪费时间了,还是求助于度娘。。。
然后,看到了这个老铁的博客:http://blog.csdn.net/a253664942/article/details/51051499,瞬间就明白了。下面就自己手动写下实现吧!

简单粗暴

这位老铁的方法二虽然时间复杂度高一点,却是较为直接、简单的,那就先写方法二的实现吧:

import java.util.Arrays;

/**
 * Created by clearbug on 2018/2/26.
 */
public class Solution {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            int[] arr = Utils.intArray(i + 1);
            System.out.println("arr = " + Arrays.toString(arr) + ", maxSubSum = " + getMaxSubSum(arr));
        }
    }

    // aNotFound404: 方法二
    public static int getMaxSubSum(int[] arr) {
        int currSum = 0, maxSum = 0;
        for (int i = 0; i < arr.length; i++) {
            currSum += arr[i];
            if (currSum < 0) {
                currSum = arr[i];
            }
            if (currSum > maxSum) {
                maxSum = currSum;
            }
        }
        return maxSum;
    }

}

不过 aNotFound404: 方法二逻辑上有些看不明白,所以我自己写了个工具类来进行了下测试工作:

import java.util.Arrays;
import java.util.Random;

/**
 * Created by clearbug on 2018/3/2.
 */
public class Utils {

    public static void main(String[] args) {
        System.out.println(Arrays.toString(intArray(3)));
        System.out.println(Arrays.toString(intArray(5)));
        System.out.println(Arrays.toString(intArray(7)));
    }

    public static int[] intArray(int len) {
        int[] res = new int[len];

        Random rand = new Random();
        for (int i = 0; i < len; i++) {
            res[i] = rand.nextInt(100) - 50;
        }
        return res;
    }
}

然后 Solution 类 main 方法的运行结果如下:

arr = [-42], maxSubSum = 0
arr = [5, 23], maxSubSum = 28
arr = [-50, 21, -26], maxSubSum = 21
arr = [29, -25, 16, -18], maxSubSum = 29
arr = [-31, 7, 45, 11, -19], maxSubSum = 63
arr = [15, -47, 41, 12, 29, 2], maxSubSum = 84
arr = [8, -3, -3, 17, -1, -36, 12], maxSubSum = 19
arr = [-33, 48, -4, -16, -44, 20, 10, -45], maxSubSum = 30
arr = [33, 42, 49, 3, -18, 38, 19, -9, -41], maxSubSum = 166
arr = [33, 23, -2, -11, -16, 35, 16, 46, 13, 1], maxSubSum = 138

可以看到第八次测试的结果明显是错误的,应该是 48,而不是 20 + 10 = 30
好吧,这位 aNotFound404 老铁的博客就先不看了吧,免得被误导。。。
然后我又搜索到了另外一位老铁的博客,http://blog.csdn.net/wangzhiyu1980/article/details/51392500。从他的博客上来看,这道题目应该是《编程之美》这本书上的原题,看来刷算法题的话《剑指Offer》和《编程之美》这两本书还是必看的啊!
然后,zy 这位老铁说这道题的解法使用了动态规划的思想,但是我之前并不知道什么是动态规划,然后我又搜索了下动态规划是什么鬼?看了下面这两篇文章基本上有点认识了:
https://www.zhihu.com/question/23995189
http://www.sohu.com/a/153858619_466939?p=wechat
好了,现在大概是理解动态规划了。那么,怎么解决这道题目呢?好吧,想了一会我还是不知道如何使用动态规划来解决这个问题。。。直接下载了《编程之美》这本书的pdf版本来看解法吧!

解法一

import java.util.Arrays;

/**
 * Created by clearbug on 2018/2/26.
 */
public class Solution {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            int[] arr = Utils.intArray(i + 1);
            System.out.println("arr = " + Arrays.toString(arr) + ", maxSubSum = " + maxSubSum1(arr));
        }
    }

    /**
     * 《编程之美》解法一:穷举法
     * 
     * 时间复杂度:O(n^3)
     * 
     * @param arr 目标数组
     * @return 最大子序列和
     */
    public static int maxSubSum1(int[] arr) {
        int res = Integer.MIN_VALUE;

        for (int i = 0; i < arr.length; i++) {
            for (int j = i; j < arr.length; j++) {
                int sum = 0;
                for (int k = i; k <= j; k++) {
                    sum += arr[k];
                }
                if (sum > res) {
                    res = sum;
                }
            }
        }

        return res;
    }
}

仔细考虑下,其实第三层循环是没有必要的,所以做一下优化:

/**
 * 《编程之美》解法一:穷举法-优化版
 *
 * 时间复杂度:O(n^2)
 *
 * @param arr 目标数组
 * @return 最大子序列和
 */
public static int maxSubSum1Opt(int[] arr) {
    int res = Integer.MIN_VALUE;

    for (int i = 0; i < arr.length; i++) {
        int sum = 0;
        for (int j = i; j < arr.length; j++) {
            sum += arr[j];
            if (sum > res) {
                res = sum;
            }
        }
    }

    return res;
}

参考

http://blog.csdn.net/a253664942/article/details/51051499
https://www.zhihu.com/question/23995189
http://www.sohu.com/a/153858619_466939?p=wechat

以上是关于求一个整形数组最大子序列的和的主要内容,如果未能解决你的问题,请参考以下文章

返回一个整形数组中最大子数组的和

返回一个整数数组中最大子数组的和

返回一个二维数整数组中最大子数组的和

二维数组求最大连通子数组的和

软件工程个人作业04(求数组最大子数组的和)

算法01整形数组的最大和