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