最大子列和问题

给定K个整数组成的序列{ N​1 , N2 , … , NK },“连续子列”被定义为{ Ni , N​i+1​ , …, Nj },其中1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

输入格式:

输入第1行给出正整数K (≤100000);第2行给出K个整数,其间以空格分隔。

输出格式:

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

输入样例:

6
-2 11 -4 13 -5 -2

输出样例:

20

思路之一

使用递归的思路,采用分而治之的方法,具体如下:
第1步:将序列从中间分为左右子列两部分;
第2步:递归求得左右子列的最大和S,S
第3步:从中间分别向左右扫描,找出跨分界线的最大子列和S
第4步:Smax = max{S,S,S};

C实现

# include 

int getMaxValue3(int a, int b, int c) {
    return a > b ? a > c ? a : c : b > c ? b : c;
}

int divideAndConquer(int list[], int left, int right) {
    //存储左右子列最大和
    int maxLeftSum = 0 , maxRightSum = 0;
    //存储跨边界左右子列最大和
    int maxLeftBorderSum = 0 , maxRightBorderSum = 0;

    //递归调用出口,子列只有一个值时
    if (left == right) {
        if (list[left]) 
            return list[left];
        else
            return 0;
    }

    //计算中间索引
    int center = (left + right) / 2;

    //计算跨边界的左右子列最大和
    int leftBorderSum = 0, rightBorderSum = 0;
    //从左边扫描
    for (int i = center; i >= left; i--) {
        leftBorderSum += list[i];
        if (leftBorderSum > maxLeftBorderSum)
            maxLeftBorderSum = leftBorderSum;
    }
    //从右边扫描
    for (int i = center+1; i <= right; i++) {
        rightBorderSum += list[i];
        if (rightBorderSum > maxRightBorderSum)
            maxRightBorderSum = rightBorderSum;
    }

    //返回最大子列和
    return getMaxValue3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);
}

//统一函数接口
int getMaxSeqSum(int list[], int n) {
    return divideAndConquer(list, 0, n-1);
}

int main() {
    int n;
    scanf("%d\n",&n);
    int list[n];
    for (int i = 0; i < n; i++) {
        int elem;
        scanf("%d",&elem);
        list[i] = elem;  
    }
    printf("%d",getMaxSeqSum(list, n));
    return 0;
}

Java实现

import java.util.Scanner;

/**
 * 使用分而治之的方法计算最大子列
 */
public class MaxSeqSum {
    /**
     * 获取三个整数中的最大值
     * @param a
     * @param b
     * @param c
     * @return
     */
    public static int getMaxValue3(int a, int b, int c) {
        return a > b ? a > c ? a : c : b > c ? b : c;
    }

    public static int divideAndConquer(int [] list, int left, int right) {
        //存储左右子列的最大和
        int maxLeftSum = 0 , maxRightSum = 0;
        //存储跨分界线的左右子列最大和
        int maxLeftBorderSum = 0 , maxRightBorderSum = 0;
        //声明一些需要使用的变量
        int center, leftBorderSum, rightBorderSum;

        //递归出口,当只有一个元素时
        if (left == right) {
            if (list[left] > 0) {
                return list[left];
            } else {
                return 0;
            }
        }

        //计算中间元素索引
        center = (left + right) / 2;

        //递归计算左右子列最大和
        maxLeftSum = divideAndConquer(list, left, center);
        maxRightSum = divideAndConquer(list,center+1, right);

        //计算跨中间的左右子列最大值
        leftBorderSum = 0 ; rightBorderSum = 0 ;
        //向左扫描
        for (int i = center; i >= left; i--) {
            leftBorderSum += list[i] ;
            if (leftBorderSum > maxLeftBorderSum) {
                maxLeftBorderSum = leftBorderSum ;
            }
        }
        //向右扫描
        for (int i = center+1; i <= right; i++) {
            rightBorderSum += list[i];
            if(rightBorderSum > maxRightBorderSum) {
                maxRightBorderSum = rightBorderSum;
            }
        }

        //返回三者的最大值
        int maxSeqSum = getMaxValue3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);
        return maxSeqSum;
    }

    public static int getMaxSeqSum(int [] list, int n) {
        return divideAndConquer(list, 0, n - 1);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = Integer.parseInt(sc.nextLine());
        String[] s = sc.nextLine().split(" ");
        int[] list = new int[n];
        for (int i = 0; i < n; i++) {
            list[i] = Integer.parseInt(s[i]);
        }
        System.out.println(getMaxSeqSum(list, n));
    }
}

Python实现

def getMaxValue3(a,b,c):
	# 返回三个整数中的最大值
	return (a if (a > c) else c) if (a > b) else (b if (b > c) else c)

def divideAndConquer(list, left, right):
	# 分而治之法求list(left)到list(right)的最大子列和
	maxLeftSum , maxRightSum = 0 , 0 #存放左右子列最大和
	maxLeftBorderSum , maxRightBorderSum = 0 , 0 #存放跨分界线左右最大和


	# 递归的终止条件,即子列只有一个值
	if left == right :
		if list[left] > 0 :
			return list[left]
		else :
			return 0

	# 计算中间索引
	center = (left + right) // 2

	# 递归求左右子列最大值
	maxLeftSum = divideAndConquer(list, left, center)
	maxRightSum = divideAndConquer(list, center+1, right)


	# 求跨分界线左右最大和
	# 从左边扫描
	leftBorderSum , rightBorderSum = 0 , 0
	for i in range(center , left-1 , -1):
		leftBorderSum += list[i]
		if leftBorderSum > maxLeftBorderSum :
			maxLeftBorderSum = leftBorderSum

	#从右边扫描
	for i in range(center+1 , right+1):
		rightBorderSum += list[i]
		if rightBorderSum > maxRightBorderSum:
			maxRightBorderSum = rightBorderSum

	# 返回分而治之的结果
	return getMaxValue3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum)

def getMaxSeqSum(list, n):
	# 统一接口
	return divideAndConquer(list, 0, n-1)

def main():
	n = eval(input())
	line = input()
	list = []
	for i in line.split(" "):
		list.append(int(i))

	print(getMaxSeqSum(list, n))

main()

Scala实现

import scala.io.StdIn

object MaxSeqSum {
  /**
   * 获取三个元素中的最大值
   * @param a
   * @param b
   * @param c
   * @return
   */
  def getMaxValue3(a : Int, b : Int, c : Int) = {
    if (a > b) {if (a > c) a else c} else {if (b > c) b else c}
  }

  /**
   * 递归求最大子列和问题
   * @param list
   * @param left
   * @param right
   * @return
   */
  def divideAndConquer(list : Array[Int], left : Int, right : Int): Int = {
    //存储左右子列的最大和
    var maxLeftSum = 0 ; var maxRightSum = 0
    //存储跨边界的左右子列的最大和
    var maxLeftBorderSum = 0 ; var maxRightBorderSum = 0

    //递归调用出口,子列只有一个元素时
    if (left == right) {
      if (list(left) > 0) return list(left) else return 0
    }

    //计算中间值索引
    var centre = (left + right) / 2

    //递归计算左右子列最大和
    maxLeftSum = divideAndConquer(list, left, centre)
    maxRightSum = divideAndConquer(list, centre+1, right)

    //计算跨边界的左右子列最大和
    var leftBorderSum = 0 ; var rightBorderSum = 0
    //左扫描
    for (i <- Range(centre, left-1, -1)) {
      leftBorderSum += list(i)
      if (leftBorderSum > maxLeftBorderSum)
        maxLeftBorderSum = leftBorderSum
    }

    //右扫描
    for (i <- centre+1 to right) {
      rightBorderSum += list(i)
      if (rightBorderSum > maxRightBorderSum)
        maxRightBorderSum = rightBorderSum
    }

    return getMaxValue3(maxLeftSum, maxRightSum, maxLeftBorderSum+maxRightBorderSum)
  }

  //统一接口
  def getMaxSeqSum(list : Array[Int], n : Int): Int = {
    return divideAndConquer(list, 0, n-1)
  }

  def main(args: Array[String]): Unit = {
    val n = StdIn.readLine().toInt
    val list = StdIn.readLine().split(" ").map(_.toInt)
    println(getMaxSeqSum(list,n))
  }
}

你可能感兴趣的:(Code练习)