连续子数组的最大和
2016-05-11 12:55
351 查看
题目描述
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?
思路大概有3种。
暴力穷举法
分治递归
动态规划
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?
思路大概有3种。
暴力穷举法
分治递归
动态规划
import java.util.Scanner; public class FindGreatestSumOfSubArray { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("the size of array:"); int n = scanner.nextInt(); int[] array = new int ; System.out.println("input the array:"); for (int i = 0; i < n; i++) { array[i] = scanner.nextInt(); } System.out.println("max sumOfSubArray is:" + FindGreatestSumOfSubArray(array)); } // 方法1:暴力穷举法 public static int FindGreatestSumOfSubArray(int[] array) { int len = array.length; if (len == 0) { return 0; } int maxSum = array[0]; for (int i = 0; i < len - 1; i++) { int partSum = array[i]; if (partSum > maxSum) { maxSum = partSum; } for (int j = i + 1; j < len; j++) { partSum += array[j]; if (partSum > maxSum) { maxSum = partSum; } } } return maxSum; } // 方法2:分治递归方法 o(N*log2N) public static int FindGreatestSumOfSubArray1(int[] array) { int len = array.length; if (len == 0) { return 0; } return maxSumOfSubArray(array, 0, len - 1); } // 递归求解 public static int maxSumOfSubArray(int[] array, int left, int right) { if (left == right) { return array[left]; } int mid = (left + right) / 2; // 前半部分最大子数组 int leftMaxSub = maxSumOfSubArray(array, left, mid); // 后半部分最大子数组 int rightMaxSub = maxSumOfSubArray(array, mid + 1, right); // 中点向左最大子数组 int maxOfMidLeft = maxSubArray(array, mid, left); // 中点向右最大子数组 int maxOfMidRight = maxSubArray(array, mid + 1, right); int midMaxSub = maxOfMidLeft + maxOfMidRight; // 返回3种情况的最大值 int maxSub = leftMaxSub > rightMaxSub ? leftMaxSub : rightMaxSub; return maxSub > midMaxSub ? maxSub : midMaxSub; } // 求left到right的最大子数组的最大值 public static int maxSubArray(int[] array, int left, int right) { int maxSub = array[left]; if (left == right) { return maxSub; } int tempSub = maxSub; int flag = left < right ? 1 : -1; if (flag == 1) { for (int i = left + 1; i <= right; i++) { tempSub += array[i]; if (tempSub > maxSub) { maxSub = tempSub; } } } else { for (int i = left - 1; i >= right; i--) { tempSub += array[i]; if (tempSub > maxSub) { maxSub = tempSub; } } } return maxSub; } // 动态规划 O(N)复杂度 // all[i-1] = // max{array[i-1],array[i-1]+Start[i],all[i]},其中Start[i]是指array[i],...,array[len-1]中从array[i]开始的最大子数组 // all[i]指array[i],...,array[len-1]中的最大子数组之和 public static int FindGreatestSumOfSubArray2(int[] array) { int len = array.length; if (len == 0) { return 0; } int[] all = new int[len]; int[] start = new int[len]; all[len - 1] = array[len - 1]; start[len - 1] = array[len - 1]; for (int i = len - 2; i >= 0; i--) { start[i] = Math.max(start[i + 1] + array[i], array[i]); all[i] = Math.max(start[i], all[i + 1]); } return all[0]; } // 动态规划的改进 o(1)的空间 public static int FindGreatestSumOfSubArray3(int[] array) { int len = array.length; if (len == 0) { return 0; } int all = array[len - 1]; int start = array[len - 1]; for (int i = len - 2; i >= 0; i--) { start = Math.max(start + array[i], array[i]); all = Math.max(start, all); } return all; } }
相关文章推荐
- 《编程之美》
- 2012年终碎语,编程之美
- 失业在家的学习笔记-第二天
- 编程之美2015初赛A
- 编程之美初赛B
- 程序员编程艺术3:寻找最小的k个数
- 编程之美2013全国挑战赛资格赛第1题
- 编程之美2013全国挑战赛资格赛第3题
- 编程之美3.8:求二叉树节点的最大距离
- 瓷砖覆盖地板问题
- Best Time to Buy and Sell Stock
- 编程之美2014格格取数
- 编程之美——象棋将帅问题
- 编程之美——烙饼排序问题
- 连连看游戏判断两个块是否可以消去,并计算最小转弯数
- 《编程之美》——中国象棋将帅问题
- 《编程之美》——求二叉树中节点的最大距离(非递归)
- 《编程之美》——求二叉树中节点的最大距离(非递归)
- 《编程之美》——中国象棋将帅问题
- 连连看游戏判断两个块是否可以消去,并计算最小转弯数