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

maxSubArray

Only My Railgun

每天一个小程序(十二)--- max SubArray_第1张图片

前言:

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


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.
 * 

* Example: *

* Input: [-2,1,-3,4,-1,2,1,-5,4], * Output: 6 * Explanation: [4,-1,2,1] has the largest sum = 6. * Follow up: *

* 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)

你可能感兴趣的:(学习,java小程序,java,遇到的问题)