每天一个小程序(十二)--- max SubArray

maxSubArray

Only My Railgun

超电磁炮

前言:

周六和老婆去爬山,山上好多杨梅中途差点放弃,后来还是爬到了山顶,感觉一周的不快都得到了释放~ 周天再次和小伙伴相约去了一个新的密室,千与千寻主题,难度其实有点稍低了,不过场景之类的还是很还原的,比上次体验好很多了,加上晚上的火锅,愉快的一天~ ?


package array;


/**
 * @author BlackSugar
 * @date 2019/4/16
 * Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
 * <p>
 * Example:
 * <p>
 * Input: [-2,1,-3,4,-1,2,1,-5,4],
 * Output: 6
 * Explanation: [4,-1,2,1] has the largest sum = 6.
 * Follow up:
 * <p>
 * If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
 */
public class MaximumSubarray {
    /**
     * 获取具有最大值的子数组
     * 思路:已经说了用分治的方法,我们先实现O(n)的方法
     * 1、首先肯定就是迭代走起,如果最复杂的肯定是双循环,不过这个复杂度达到了O(n^2),不符合要求
     * 2、获取最大值,肯定是要在两个正数当中产生,找到第一个正数为起始迭代,若加起来为负数,则sum归位,然后取最大值
     * 3、归并分治法,感觉还没有DP方便,将值递归拆分为一个个左右小块,再依次合并起来,期间比较左右最大值或者两者之间有最大值, O(nlogn)
     * [-2,1,-3,4,-1,2,1,-5,4]--->[-2,1,-3,4,-1]+[2,1,-5,4]--->[-2,1,-3]+[4,-1] + [2,1]+[-5,4]
     * --->[-2,1]+[-3] + [4]+[-1]...
     *
     * @param nums
     * @return
     */
    public int maxSubArray(int[] nums) {
        if (null == nums || nums.length == 0) {
            return 0;
        }
        /*int sum = 0, max = nums[0];
        for (int num : nums) {
            sum = sum > 0 ? sum + num : num;
            max = Math.max(sum, max);
        }*/

        //分治法

        int max = maxSubArrayHelper(nums, 0, nums.length - 1);

        return max;
    }

    private int maxSubArrayHelper(int[] nums, int start, int end) {
        if (start == end) {
            return nums[start];
        }
        int mid = (end + start) / 2;
        int sum = 0, max;

        int left = maxSubArrayHelper(nums, start, mid);
        int right = maxSubArrayHelper(nums, mid + 1, end);
        max = Math.max(left, right);

        int localMax1 = Integer.MIN_VALUE;
        for (int i = mid; i >= start; i--) {
            sum += nums[i];
            localMax1 = Math.max(sum, localMax1);
        }

        int localMax2 = Integer.MIN_VALUE;
        sum = 0;
        for (int i = mid + 1; i <= end; i++) {
            sum += nums[i];
            localMax2 = Math.max(sum, localMax2);
        }
        return Math.max(localMax1 + localMax2, max);
    }

    public static void main(String[] args) {
        System.out.println(new MaximumSubarray().maxSubArray(new int[]{-2, 1, -3, 4, -1, -2, 1, -5, 4}));
    }
}

总结:

这道题要找最大的子串,一般采用DP会方便一点,利用最大子串肯定前半部分不能小于0的规则记录sum和最大值,每次sum与最大值进行比较取大,小于0则置为当前值;
题目要求用分治法,则需要判断子串是在左串还是右串或者之间,然后归并即可

1、DP时间复杂度O(n)
2、分治时间复杂度O(nlogn)

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值