给定一个整数数组  ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

  1. **输入:** [-2,1,-3,4,-1,2,1,-5,4],
  2. **输出:** 6
  3. **解释:** 连续子数组 [4,-1,2,1] 的和最大,为 6
  1. public int MaxsubArray1(int nums[]) {
  2. int Sum = 0, MaxSum = 0;
  3. int N = nums.length; //获得当前数组个数
  4. for(int i = 0; i < N; i++) {
  5. Sum = 0;
  6. for(int j = i; j < N; j++) {
  7. Sum += nums[j];
  8. if(Sum > MaxSum) { //比较子列和,当大于最大项时
  9. MaxSum = Sum;
  10. }
  11. }
  12. }
  13. return MaxSum;
  14. }

复杂度分析:

  • 时间复杂度:O(N^2) 遍历两次数组
  • 空间复杂度:O(1) 使用常数空间
  1. public int MaxsubArray2(int nums[]) {
  2. int Sum = 0, MaxSum = 0;
  3. int N = nums.length; //获得当前数组个数
  4. for(int i = 0; i < N; i++) {
  5. sum += nums[i];
  6. if(sum > MaxSum) {
  7. MaxSum = sum;
  8. }else if(sum < 0) {
  9. sum = 0;
  10. }
  11. }
  12. return MaxSum;
  13. }

算法分析:

  1. 数组边移动边处理,之前的子序和若为负,继续移动至最右端。

复杂度分析:

  • 时间复杂度:O(N)遍历一次数组
  • 空间复杂度:O(1)使用常数空间
  1. public static int MaxSubArray3 (int nums[]) {
  2. int N = nums.length();
  3. if(N < 1) {
  4. return 0;
  5. }
  6. int left = 0;
  7. int right = N - 1;
  8. return DivideAndConquer(nums, left, right);
  9. }
  10. public static int DivideAndConquer(int nums[], int left, int right) {
  11. //当子序列个数为1时
  12. if(left == right) {
  13. if(nums[left] > 0) {
  14. return nums[left];
  15. }else return 0;
  16. }
  17. //当子序列个数大于1时, 分别求左右子序列和
  18. int mid = (left + right)/2;
  19. int MaxLeftSum = DivideAndConquer(nums, left, mid);
  20. int MaxRightSum = DivideAndConquer(nums, mid, right);
  21. /*求中子序列和(跨分界线)*/
  22. //分界线左边
  23. int MaxLeftBorderSum = 0, int LeftBoderSum = 0;
  24. for(int i = mid; i >= left; i--) {
  25. LeftBoderSum += nums[i];
  26. if(LeftBoderSum > MaxLeftBorderSum) {
  27. MaxLeftBorderSum = LeftBoderSum;
  28. }
  29. }
  30. //分界线右边
  31. int MaxRightBorderSum = 0, int RightBoderSum = 0;
  32. for(int j = mid; j <= right; j++) {
  33. RightBoderSum += nums[j];
  34. if(RightBoderSum > MaxRightBorderSum) {
  35. MaxRightBorderSum = RightBoderSum;
  36. }
  37. }
  38. //中子序列和
  39. int MaxBorderSum = MaxLeftBorderSum + MaxRightBorderSum;
  40. return MaxThree(MaxBorderSum, MaxLeftSum, MaxRightSum);
  41. }
  42. /*找出三数中最大值
  43. */
  44. public static int MaxThree(int a, int b, int c) {
  45. return a > b ? a > c ? a : c : b > c ? b : c;
  46. }

算法分析:

  1. 将问题分解为小问题,再用递归求解。最后合并小问题的解得到问题的解。
  2. 假设最大子序列有n个数字,当n==1时,直接返回该数字;当n\>1时,分为左子序列和、右子序列和、中子序列和(包括左右子序列的元素)。这里来自leetcode的讨论区的图更好理解:


复杂度分析:

  • 时间复杂度:O(NlogN)最多需要N次递归
  • 空间复杂度:O(logN) 递归树的深度

版权声明:本文为EthanWong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/EthanWong/p/12678707.html