求最大子序列和的问题

package com.xhm.sjjg;

 

/**
 * 求最大子序列和的问题
 * 问题描述: 给定一串int型数字(可正可负,本例中使用数组实现),
 * 寻求其中的一个子序列, 要求其所有项的值相加之和,
 * 为这一串数字所存在的子序列中各项的值相加之和为最大的,
 * 并返回那个序列各项的值相加之和。
 */
public class SubsqueenceTest
{
 /**
  * 方法1:一般实现方式
  * 该方式清晰明了,分别计算每个可能的子序列之和
  * 然后通过比较,始终将每个可能的子序列之和的最大值进行保存返回
  * 但该方式效率最低 O(N^3)
  */
 public static int getMaxSubSum1(int[] sub)
 {
  int maxSum = 0;

  for (int i = 0; i < sub.length; i++)
  {
   for (int j = i; j < sub.length; j++)
   {
    int sum = 0;

    for (int n = i; n <= j; n++)
    {
     sum += sub[n];
    }

    if (sum > maxSum)
    {
     maxSum = sum;
    }
   }
  }
  return maxSum;
 }

 /**
  * 方法2:针对方法1优化过的实现 O(N^2)
  */
 public static int getMaxSubSum2(int[] sub)
 {
  int maxSum = 0;

  for (int i = 0; i < sub.length; i++)
  {
   int sum = 0;
   for (int j = i; j < sub.length; j++)
   {
    sum += sub[j];

    if (sum > maxSum)
    {
     maxSum = sum;
    }
   }
  }

  return maxSum;
 }

 /**
  * 返回三个int型数字的最大值
  */
 private static int max(int a, int b, int c)
 {
  int max = 0;

  if (a > b)
  {
   max = a;
  } else
  {
   max = b;
  }

  if (c > max)
  {
   max = c;
  }

  return max;
 }

 /**
  * 该方法为方法3调用
  * 通过递归来获取最大子序列的和
  */
 private static int maxSubRecursive(int[] sub, int left, int right)
 {
  if (left == right)
  {
   return sub[left];
  }

  int center = (left + right) / 2;

  // 用来记录左部分的最大子序列之和
  int maxLeft = maxSubRecursive(sub, left, center);
  // 用来记录右部分的最大子序列之和
  int maxRight = maxSubRecursive(sub, center + 1, right);

  // 用来记录左部分包含最后一个元素的最大子序列之和
  int maxLeftBorder = 0;
  int leftBorder = 0;
  for (int i = center; i >= left; i--)
  {
   leftBorder += sub[i];

   if (leftBorder > maxLeftBorder)
   {
    maxLeftBorder = leftBorder;
   }
  }

  // 用来记录右部分包含第一个元素的最大子序列之和
  int maxRightBorder = 0;
  int rightBorder = 0;
  for (int i = center + 1; i <= right; i++)
  {
   rightBorder += sub[i];

   if (rightBorder > maxRightBorder)
   {
    maxRightBorder = rightBorder;
   }
  }

  return max(maxLeft, maxRight, maxLeftBorder + maxRightBorder);
 }

 /**
  * 方法3:采用“分治”策略 O(N*logN)
  * 基本思想:
  * 将数字序列分为2部分,
  * 那最大和的出现将存在3种可能:1、左部分  2、右部分  3、跨越左右两部分,占据序列的中间
  * 取他们中间的最大者即为最大子序列的和
  */
 public static int getMaxSubSum3(int[] sub)
 {
  return maxSubRecursive(sub, 0, sub.length - 1);
 }

 /**
  * 方法4:动态规划实现  O(N)
  * 原理:主要在子序列的起点定位上
  * 在数字序列中任何一个以负数作为起点的子序列,
  * 都不可能是最优序列的起点,我们总是可以其后边的项作为起点来优化它
  * 同理,任何负的子序列也不可能是最优序列的起点
  */
 public static int getMaxSubSum4(int[] sub)
 {
  int maxSum = 0;
  int sum = 0;

  for (int i = 0; i < sub.length; i++)
  {
   sum += sub[i];

   if (sum > maxSum)
   {
    maxSum = sum;
   } else if (sum < 0)//关键
   {
    sum = 0;
   }
  }

  return maxSum;
 }

 public static void main(String[] args)
 {
  int[] sub = { 3, 11, -7, 15, -5, -2 ,23,-3,10};

  System.out.println("getMaxSubSum1 = "
    + SubsqueenceTest.getMaxSubSum1(sub));
  System.out.println("getMaxSubSum2 = "
    + SubsqueenceTest.getMaxSubSum2(sub));
  System.out.println("getMaxSubSum3 = "
    + SubsqueenceTest.getMaxSubSum3(sub));
  System.out.println("getMaxSubSum4 = "
    + SubsqueenceTest.getMaxSubSum4(sub));
 }

}

你可能感兴趣的:(C++,c,C#,J#)