连续子序列最大和问题!!!

本文涉及要点:

  • 通过System.currentTimeMillis()计算程序运行时间
  • 通过random.nextInt(num)+1得到1-num之间的随机数
  • 巧妙地生成了一些负数

代码部分:

1、类的概览:

public class ProgramList1 {
	static int seqStart = 0;
	static int seqEnd = 0;
	static long time = 0;
	
	主函数:
	public static void main(String[] args){	}
	
	初始化数组函数
	public static int[] initArray(int arrayParamNum) {	}
	
	根据用户键入调用指定的函数
	public static int execFunction(int n, int[] a) {	}
	
	// 蛮力算法(戏称:费劲算法)求连续子序列最大和问题,时间复杂度为O(N的立方),N为数组长度
	public static int maxSubsequenceSum1(int[] a) {	}
	
	// 蛇皮简化蛮力算法,时间复杂度为O(N的平方),N为数组长度
	public static int maxSubsequenceSum2(int[] a) {	}
	
	// 究极蛇皮简化蛮力算法求解最大子序列和问题,时间复杂度为线性的。	
	public static int maxSubsequenceSum3(int[] a) {	}

下面将呈现每个函数的具体内容:

1、主函数:

public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int a[] = {};
		while (true) {
			System.out.print("请输入数组元素的个数:");
			int arrayParamNum = input.nextInt();
			System.out.print("请输入要调用的函数编号:(1-蛮力法;2-蛮力法改良;3-蛮力法究极改良;)");
			int funcNum = input.nextInt();
			a = initArray(arrayParamNum);
			System.out.println();
			System.out.println("子序列最大和为" + ProgramList1.execFunction(funcNum, a));
			System.out.println("子序列最大和对应子序列为从第" + (seqStart + 1) + "到第" + (seqEnd + 1) + "个元素分别为:" + a[seqStart] + "和"
					+ a[seqEnd]);
			System.out.println("运行了" + time / 1000 + "秒");
			System.out.print("是否退出?0-退出;1-继续");
			int c_or_b = input.nextInt();
			if (c_or_b == 0) {
				break;
			} else {
				continue;
			}
		}
	}

2、初始化数组函数:

public static int[] initArray(int arrayParamNum) {
		Random random = new Random();
		int tempnum = 0;
		int a[] = new int[arrayParamNum];
		for (int i = 0; i < arrayParamNum; i++) {
			tempnum = random.nextInt(arrayParamNum) + 1;
			a[i] = (int) (tempnum * Math.pow(-1, i));// 生成既有负数又有正数的数组;由于random.nextInt()只能生成正数,无奈只能采用这种办法生成负数;
			if (i % 10 == 0 && i != 0) {// 控制每行10个数
				System.out.println();
			}
			System.out.print(a[i] + "    ");
		}
		return a;
	}

3、根据用户键入调用指定函数:

public static int execFunction(int n, int[] a) {
		if (n == 1) {
			return ProgramList1.maxSubsequenceSum1(a);
		} else if (n == 2) {
			return ProgramList1.maxSubsequenceSum2(a);
		} else {
			return ProgramList1.maxSubsequenceSum3(a);
		}
	}

4、蛮力算法(费劲算法):

public static int maxSubsequenceSum1(int[] a) {// 蛮力算法求连续子序列最大和问题,时间复杂度为O(N的立方),N为数组长度
		int maxSum = 0;
		long startTime = System.currentTimeMillis();
		for (int i = 0; i < a.length; i++) {// 控制子序列头元素
			for (int j = i; j < a.length; j++) {// 控制子序列的尾元素
				int thisSum = 0;
				for (int k = i; k <= j; k++) {// 求每个子序列的和
					thisSum += a[k];
				}
				if (thisSum > maxSum) {// 记录最大子序列和,以及对应的下标
					maxSum = thisSum;
					seqStart = i;
					seqEnd = j;
				}
			}
		}
		long endTime = System.currentTimeMillis();
		time = endTime - startTime;
		return maxSum;
	}

5、改良费劲算法:

public static int maxSubsequenceSum2(int[] a) {// 蛇皮简化蛮力算法,时间复杂度为O(N的平方),N为数组长度
		int maxSum = 0;
		long startTime = System.currentTimeMillis();
		for (int i = 0; i < a.length; i++) {// 控制子序列开头
			int thisSum = 0;
			for (int j = i; j < a.length; j++) {// 控制子序列结尾,并且求和
				thisSum += a[j];
				if (thisSum > maxSum) {// 记录最大子序列和,以及对应的下标
					maxSum = thisSum;
					seqStart = i;
					seqEnd = j;
				}
			}
		}
		long endTime = System.currentTimeMillis();
		time = endTime - startTime;
		return maxSum;
	}

6、究极改良费劲算法:

public static int maxSubsequenceSum3(int[] a) {// 究极蛇皮简化蛮力算法求解最大子序列和问题,时间复杂度为线性的。
		int maxSum = 0;
		int thisSum = 0;
		long startTime = System.currentTimeMillis();
		for (int i = 0, j = 0; j < a.length; j++) {
			thisSum += a[j];
			if (thisSum > maxSum) {
				maxSum = thisSum;
				seqStart = i;
				seqEnd = j;
			} else if (thisSum < 0) {//如果thisSum<0了就说明maxSum已经开始减小了,所以就要改变i的值
				i = j + 1;
				thisSum = 0;
			}
		}
		long endTime = System.currentTimeMillis();
		time = endTime - startTime;
		return maxSum;
	}

后三个方法我是用调试功能,才充分理解了每一步的原理,希望能帮到大家!!
如果觉得有用请留下您的赞?
文章不尽完美,大家凑合着看;
如有高人认为小弟的文章有改进的地方,请评论区指点一下。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值