实验一 分治策略
1.实验要求
1、理解递归的概念,掌握设计有效算法的分治策略。
2、分治法求解最大连续子数组(字段和)问题
2.实验语言
Java
3.算法复杂度分析
算法的时间复杂度为 O(n log n),其中 n 是数组的长度。
4.代码实现
package shiyan1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
public class MaxSubarray {
public static void main(String[] args) {
// 生成随机整数数组
int[] array = generateRandomIntegers(1000, -1000, 1000);
// 将数组写入文件
writeInputFile("input.txt", array);
// 读取输入文件
int[] inputArray = readInputFile("input.txt");
// 计算最大连续子数组
int[] maxSubarray = findMaxSubarray(inputArray, 0, inputArray.length - 1);
System.out.println("大连续子数组"+Arrays.toString(maxSubarray));
// 计算最大连续子数组的和
int maxSum = calculateSum(maxSubarray);
System.out.println("最大连续子数组的和"+maxSum);
// 将结果输出到文件
writeOutputFile("output.txt", maxSubarray, maxSum);
}
// 生成指定数量的随机整数数组
private static int[] generateRandomIntegers(int count, int minValue, int maxValue) {
int[] array = new int[count];
Random random = new Random();
for (int i = 0; i < count; i++) {
array[i] = random.nextInt(maxValue - minValue + 1) + minValue;
}
return array;
}
// 将整数数组写入文件
private static void writeInputFile(String filename, int[] array) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < array.length; i++) {
sb.append(array[i]);
if (i < array.length - 1) {
sb.append(",");
}
}
writer.write(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
// 读取输入文件并返回整数数组
private static int[] readInputFile(String filename) {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line = reader.readLine();
String[] values = line.split(",");
int[] array = new int[values.length];
for (int i = 0; i < values.length; i++) {
array[i] = Integer.parseInt(values[i]);
}
return array;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// 寻找最大连续子数组
private static int[] findMaxSubarray(int[] array, int low, int high) {
// 基本情况:只有一个元素
if (low == high) {
int[] baseCase = { array[low] };
return baseCase;
}
// 将数组划分为两部分
int mid = (low + high) / 2;
int[] leftSubarray = findMaxSubarray(array, low, mid);
int[] rightSubarray = findMaxSubarray(array, mid + 1, high);
int[] crossSubarray = findMaxCrossingSubarray(array, low, mid, high);
// 比较左子数组、右子数组和跨越中点的子数组,返回最大者
if (calculateSum(leftSubarray) >= calculateSum(rightSubarray) && calculateSum(leftSubarray) >= calculateSum(crossSubarray)) {
return leftSubarray;
} else if (calculateSum(rightSubarray) >= calculateSum(leftSubarray) && calculateSum(rightSubarray) >= calculateSum(crossSubarray)) {
return rightSubarray;
} else {
return crossSubarray;
}
}
// 寻找跨越中点的最大连续子数组
private static int[] findMaxCrossingSubarray(int[] array, int low, int mid, int high) {
// 寻找包含中点左侧的最大连续子数组
int leftSum = Integer.MIN_VALUE;
int sum = 0;
int maxLeft = mid;
for (int i = mid; i >= low; i--) {
sum += array[i];
if (sum > leftSum) {
leftSum = sum;
maxLeft = i;
}
}
// 寻找包含中点右侧的最大连续子数组
int rightSum = Integer.MIN_VALUE;
sum = 0;
int maxRight = mid + 1;
for (int i = mid + 1; i <= high; i++) {
sum += array[i];
if (sum > rightSum) {
rightSum = sum;
maxRight = i;
}
}
// 构造跨越中点的最大连续子数组
int[] crossSubarray = new int[maxRight - maxLeft + 1];
System.arraycopy(array, maxLeft, crossSubarray, 0, crossSubarray.length);
return crossSubarray;
}
// 计算数组的和
private static int calculateSum(int[] array) {
int sum = 0;
for (int num : array) {
sum += num;
}
return sum;
}
// 将结果输出到文件
private static void writeOutputFile(String filename, int[] maxSubarray, int maxSum) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < maxSubarray.length; i++) {
sb.append(maxSubarray[i]);
if (i < maxSubarray.length - 1) {
sb.append(",");
}
}
writer.write(sb.toString() + "\n");
writer.write(String.valueOf(maxSum));
} catch (IOException e) {
e.printStackTrace();
}
}
}
输入内容
运行
输出