JAVA代码求解最大子段和问题

本文介绍如何利用分治策略解决最大子段和问题。通过分析数组,发现当长度为2时,可以通过比较求解,大于2则递归划分为小数组。定义DSZ方法来找到前后半段连接的最大子段和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@[TOC]java代码求解最大子段和问题

什么是最大子段和问题

给定一个数组(元素已知),元素由正整数,负整数两种元素组成,现在求该数组中从哪个位置到哪个位置对应元素所组成的子段和最大,这个子段和就叫做最大子段和。

分析问题(分治思想)

最大子段和不是在“前半段”(a[0] ~ a[mid])就是在“后半段”a[mid+1] ~ a[a,length-1],要么就是由“前半段部分元素和后半段部分元素连接起来a[i] ~ a[j]所构成(其中i(从mid ~ 0),j(从mid+1) ~ (a.length -1);”
就以数组a[] = {-1,3,2}为例
就以a[] = {-1,3,2}为例
前半段从-1 ~3 后半段从2 ~ 2(也就是它本身) DSZ就指的是前半段和后半段所连接的“累加和最大的”子段和
之后我们可以判断这三个值的大小 从而得出当前数组的最大子段和

发现捷径

当数组长度为2时可以比较a,b,a+b三个数的大小 从而选出最大值即为最大子段和

当数组长度大于2时 需递归调用方法将数组划分为长度等于2的小数组,逐步得到所要求数组的最大子段和。

因为当将数组划分到长度等于2的时候对应的小长度数组的最大子段和可以轻松的求解出来,进而一步步向所求数组一步步靠拢进而得到最终的最大子段和。

if(mid == 0){
			x = a[0];
			y = a[1];
			z = x + y;
			if(x > y){
				max = x;
			}
			else max = y;
			if(max > z){
				max = max;
			}
			else {max = z;}
		return max;
		}

定义一个DSZ方法,用于返回当前数组前半段和后半段连接所构成的“累加和最大的”子段和

public static int DSZ(int a[]){
		int mid = (a.length-1)/2;
		int H = a.length;
		int i,j,max,x,y,z,L,D;
		if(H%2 != 0){
			L = mid+1;
			D = mid ;
		}
		else {
			L = mid +1;
			D = mid +1; 
		}
		int[] d = new int[L];
		int[] e = new int[D];
		for(max = 0,i = mid,j = 0;i >=0;i--,j++){
			max += a[i];
			d[j] = max;
		}
		for(max = 0,i = (mid+1),j = 0;i < a.length;i++,j++){
			max += a[i];
			e[j] = max;
		}
		x = mid - ZDS(d);           
		y = mid +ZDS(e)+1;
		for(max = 0,i = x;i <= y;i++){
			max += a[i];
		}
		return max;
	}

定义ZDS(最大数)方法用于辅佐DSZ方法求出前半段和后半段“累加和最大”的子段和

public static int ZDS(int a[]){
		int max,i,j = 0;
		for(i = 0,max = 0;i < a.length;i++){
			if(max < a[i]){
				max = a[i];
			}
		}
		for(i = 0;i < a.length;i++){
			if(max == a[i]){
				j = i;
			}
		}
	return j;
	}

排版方法

方法大致排版

import java.util.Scanner;
public class ZDZD4{
	public static void main(String[] args){
		System.out.println("请输入数组元素并用逗号隔开:");
		Scanner s1 = new Scanner(System.in);
		String str = s1.next().toString();
		String[] b = str.split(",");
		int[] a = new int[b.length];
		for(int j = 0;j < a.length;j++){
			a[j] = Integer.parseInt(b[j]);
			System.out.print(a[j]+" ");
		}
		System.out.println();
		System.out.print("该数组的最大子段和为:"+ZDZD1(a));
	}
	public static int ZDZD1(int a[]){
		int i,j,x,v,max,y = 0,z = 0,n = 0,m = 0,H,L,D,t,q;
		int mid = (a.length-1) / 2;
		int O = a.length;
		if(O == 1){
			return a[0];
		}
		else if(O%2 != 0){
			L = mid+1;
			D = mid ;
		}
		else{
			L = mid +1;
			D = mid +1; 
		}
		int[] b = new int[L];
		int[] c = new int[D];
		if(mid == 0){
			x = a[0];
			y = a[1];
			z = x + y;
			if(x > y){
				max = x;
			}
			else max = y;
			if(max > z){
				max = max;
			}
			else {max = z;}
		return max;
		}
		else {	
			x = DSZ(a);
			for(i = 0;i <= mid ;i++){
				b[i] = a[i];
			}
			for(v = mid+1,j= 0;v < a.length;v++){
				if(a[v] != 0){
					c[j] = a[v];
					j++;
				}
			}
			n = ZDZD1(b);
			m = ZDZD1(c);
			if(n > m){
				max = n;
			}
			else {max = m;}
			if(max > x){
				max = max;
			}
			else {max = x;}
			return max;
		}
	}
	public static int DSZ(int a[]){
		int mid = (a.length-1)/2;
		int H = a.length;
		int i,j,max,x,y,z,L,D;
		if(H%2 != 0){
			L = mid+1;
			D = mid ;
		}
		else {
			L = mid +1;
			D = mid +1; 
		}
		int[] d = new int[L];
		int[] e = new int[D];
		for(max = 0,i = mid,j = 0;i >=0;i--,j++){
			max += a[i];
			d[j] = max;
		}
		for(max = 0,i = (mid+1),j = 0;i < a.length;i++,j++){
			max += a[i];
			e[j] = max;
		}
		x = mid - ZDS(d);           
		y = mid +ZDS(e)+1;
		for(max = 0,i = x;i <= y;i++){
			max += a[i];
		}
		return max;
	}
	public static int ZDS(int a[]){
		int max,i,j = 0;
		for(i = 0,max = 0;i < a.length;i++){
			if(max < a[i]){
				max = a[i];
			}
		}
		for(i = 0;i < a.length;i++){
			if(max == a[i]){
				j = i;
			}
		}
	return j;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值