给定K个整数组成的序列{ N1 , N2 , … , NK },“连续子列”被定义为{ Ni , Ni+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中};
# 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;
}
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));
}
}
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()
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))
}
}