Java 使用D&;C/递归
我想用一个算法实现最大子数组问题,该算法显示(n log n): 查找最大连续子数组,或数组中连续元素的最大和 假设:并非所有元素都是负数Java 使用D&;C/递归,java,algorithm,recursion,divide-and-conquer,kadanes-algorithm,Java,Algorithm,Recursion,Divide And Conquer,Kadanes Algorithm,我想用一个算法实现最大子数组问题,该算法显示(n log n): 查找最大连续子数组,或数组中连续元素的最大和 假设:并非所有元素都是负数 我有一些可行的解决方案;问题在于重叠的中心数组,以及指定重叠子问题的适当索引,有些数组我在另一些数组上得到了正确的答案 只是为了比较&为了检查正确性,我实现了一个称为Kadane算法的解决方案 (我认为复杂性是ω(n)) 这是Kandane的算法(http://en.wikipedia.org/wiki/Maximum_subarray_problem)
我有一些可行的解决方案;问题在于重叠的中心数组,以及指定重叠子问题的适当索引,有些数组我在另一些数组上得到了正确的答案
只是为了比较&为了检查正确性,我实现了一个称为Kadane算法的解决方案 (我认为复杂性是ω(n)) 这是Kandane的算法(http://en.wikipedia.org/wiki/Maximum_subarray_problem):
publicstaticvoidkadane(int数组[]){
int max_end_此处=0;
for(int i=0;i
我的递归实现,使用divide&conquer比较子数组的最大值,然后对具有最大值的子数组进行递归调用,直到递归结束
public static void findMaxSubArray(int[] array, int lowIndex, int highIndex) {
int mid = 0;
int arrayLength = 0;
int maxEndingHere = 0;
if (array == null) {
throw new NullPointerException();
} else if
//base condition
(array.length < 2 || (highIndex==lowIndex)) {
maxLowIndex = lowIndex;
maxHighIndex = highIndex;
System.out.println("findMaxSubArray(int[] array, int lowIndex, int highIndex)");
System.out.println("global Max Range, low:" + maxLowIndex + " high: " + maxHighIndex);
System.out.println("global Max Sum:" + globalMaximum);
} else {
System.out.println();
int lowMidMax = 0;
int midHighMax = 0;
int centerMax = 0;
//array length is always the highest index +1
arrayLength = highIndex + 1;
//if even number of elements in array
if (array.length % 2 == 0) {
mid = arrayLength / 2;
System.out.println("low: " + lowIndex + " mid: " + mid);
for (int i = lowIndex; i < mid; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowIndex; i < mid; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = lowMidMax = maxEndingHere;
lowIndex = i;
}
}
//end low mid calc
for (int i = mid; i <= highIndex; i++) {
System.out.print(array[i] + ",");
}
System.out.println("mid: " + mid + " high: " + highIndex);
//calculate maximum contigous array encountered so far in mid to high indexes
for (int i = mid; i <= highIndex; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = midHighMax = maxEndingHere;
mid = i;
}
}
//end mid high calc
//calculate maximum contigous array encountered so far in center array
int lowCenter = mid -1;
int highCenter = highIndex -1;
System.out.println("lowCenter: " + lowCenter + " highCenter: " + highCenter);
for (int i = lowCenter; i < highCenter; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowCenter; i < highCenter; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new max found
globalMaximum = centerMax = maxEndingHere;
lowCenter = i;
}
}
//end center calc
//determine which range contains the maximum sub array
//if lowMidMax <= midHighMax and centerMax
if (lowMidMax >= midHighMax && lowMidMax >= centerMax) {
maxLowIndex = lowIndex;
maxHighIndex = mid;
//recursive call
findMaxSubArray(array, lowIndex, mid);
}
if (midHighMax >= lowMidMax && midHighMax >= centerMax) {
maxLowIndex = mid;
maxHighIndex = highIndex;
//recursive call
findMaxSubArray(array, mid, highIndex);
}
if (centerMax >= midHighMax && centerMax >= lowMidMax) {
maxLowIndex = lowCenter;
maxHighIndex = highCenter;
//recursive call
findMaxSubArray(array, lowCenter, highCenter);
}
}//end if even parent array
//else if uneven array
else {
mid = (int) Math.floor(arrayLength / 2);
System.out.println("low: " + lowIndex + " mid: " + mid);
for (int i = lowIndex; i < mid; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowIndex; i < mid; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = lowMidMax = maxEndingHere;
lowIndex = i;
}
}
//end low mid calc
System.out.println("mid+1: " + (mid + 1) + " high: " + highIndex);
for (int i = mid + 1; i <= highIndex; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in mid to high indexes
for (int i = mid + 1; i <= highIndex; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = midHighMax = maxEndingHere;
mid = i;
}
}
//end mid high calc
//calculate maximum contigous array encountered so far in center array
int lowCenter = mid;
int highCenter = highIndex -1;
System.out.println("lowCenter: " + lowCenter + " highCenter: " + highCenter);
for (int i = lowCenter; i < highCenter; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowCenter; i < highCenter; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new max
globalMaximum = centerMax = maxEndingHere;
lowCenter = i;
}
}
//end center calc
//determine which range contains the maximum sub array
//if lowMidMax <= midHighMax and centerMax
if (lowMidMax >= midHighMax && lowMidMax >= centerMax) {
maxLowIndex = lowIndex;
maxHighIndex = mid;
//recursive call
findMaxSubArray(array, lowIndex, mid);
}
if (midHighMax >= lowMidMax && midHighMax >= centerMax) {
maxLowIndex = mid;
maxHighIndex = highIndex;
//recursive call
findMaxSubArray(array, mid, highIndex);
}
if (centerMax >= midHighMax && centerMax >= lowMidMax) {
maxLowIndex = lowCenter;
maxHighIndex = highCenter;
//recursive call
findMaxSubArray(array, lowCenter, highCenter);
}
}//end odd parent array length
}//end outer else array is ok to computed
}//end method
公共静态void findMaxSubArray(int[]数组、int lowIndex、int highIndex){
int-mid=0;
int arrayLength=0;
int maxEndingHere=0;
if(数组==null){
抛出新的NullPointerException();
}否则如果
//基本条件
(array.length<2 | |(高索引==低索引)){
maxLowIndex=lowIndex;
maxHighIndex=highIndex;
System.out.println(“findMaxSubArray(int[]数组,int低索引,int高索引)”;
System.out.println(“全局最大范围,低:+maxLowIndex+”高:+maxHighIndex);
System.out.println(“全局最大和:+全局最大值”);
}否则{
System.out.println();
int lowMidMax=0;
int-midhigmax=0;
int centerMax=0;
//数组长度始终为最高索引+1
阵列长度=高指数+1;
//如果数组中的元素数为偶数
if(array.length%2==0){
mid=阵列长度/2;
System.out.println(“低:+lowIndex+”中:+mid”);
对于(int i=低指数;i=centerMax){
maxLowIndex=mid;
maxHighIndex=highIndex;
//递归调用
FindMax子阵列(阵列、中、高索引);
}
如果(centerMax>=中高Max&¢erMax>=低中高Max){
maxLowIndex=lowCenter;
maxHighIndex=高中心;
//递归调用
FindMax子阵列(阵列、低中心、高中心);
}
}//如果父数组为偶数,则结束
//如果阵列不均匀
否则{
中间=(内部)数学层(排列长度/2);
System.out.println(“低:+lowIndex+”中:+mid”);
对于(int i=低指数;i=centerMax){
maxLowIndex=mid;
maxHighIndex=highIndex;
//递归调用
FindMax子阵列(阵列、中、高索引);
}
如果(centerMax>=中高Max&¢erMax>=低中高Max){
maxLowIndex=lowCenter;
maxHighIndex=高中心;
//递归调用
FindMax子阵列(阵列、低中心、高中心);
}
}//结束奇数父数组长度
}//结束外部else数组是否可以计算
}//结束方法
结果:使用数组子数组问题1={1,2,3,4,5,6,7,8} Kadane(int数组[]):36 低:0中:4 1,2,3,4,5,6,7,8中:4高:7 低中心:6高中心:6 findMaxSubArray(int[]数组、int lowIndex、int highIndex) 全球最大范围,低:7高:7 全局最大总和:36 生成成功(总时间:0秒) 问题尽管与Kadane相比,全局最大和是正确的,但低指数和高指数范围反映了最后一次重复调用 结果:使用数组子数组
public static void findMaxSubArray(int[] array, int lowIndex, int highIndex) {
int mid = 0;
int arrayLength = 0;
int maxEndingHere = 0;
if (array == null) {
throw new NullPointerException();
} else if
//base condition
(array.length < 2 || (highIndex==lowIndex)) {
maxLowIndex = lowIndex;
maxHighIndex = highIndex;
System.out.println("findMaxSubArray(int[] array, int lowIndex, int highIndex)");
System.out.println("global Max Range, low:" + maxLowIndex + " high: " + maxHighIndex);
System.out.println("global Max Sum:" + globalMaximum);
} else {
System.out.println();
int lowMidMax = 0;
int midHighMax = 0;
int centerMax = 0;
//array length is always the highest index +1
arrayLength = highIndex + 1;
//if even number of elements in array
if (array.length % 2 == 0) {
mid = arrayLength / 2;
System.out.println("low: " + lowIndex + " mid: " + mid);
for (int i = lowIndex; i < mid; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowIndex; i < mid; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = lowMidMax = maxEndingHere;
lowIndex = i;
}
}
//end low mid calc
for (int i = mid; i <= highIndex; i++) {
System.out.print(array[i] + ",");
}
System.out.println("mid: " + mid + " high: " + highIndex);
//calculate maximum contigous array encountered so far in mid to high indexes
for (int i = mid; i <= highIndex; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = midHighMax = maxEndingHere;
mid = i;
}
}
//end mid high calc
//calculate maximum contigous array encountered so far in center array
int lowCenter = mid -1;
int highCenter = highIndex -1;
System.out.println("lowCenter: " + lowCenter + " highCenter: " + highCenter);
for (int i = lowCenter; i < highCenter; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowCenter; i < highCenter; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new max found
globalMaximum = centerMax = maxEndingHere;
lowCenter = i;
}
}
//end center calc
//determine which range contains the maximum sub array
//if lowMidMax <= midHighMax and centerMax
if (lowMidMax >= midHighMax && lowMidMax >= centerMax) {
maxLowIndex = lowIndex;
maxHighIndex = mid;
//recursive call
findMaxSubArray(array, lowIndex, mid);
}
if (midHighMax >= lowMidMax && midHighMax >= centerMax) {
maxLowIndex = mid;
maxHighIndex = highIndex;
//recursive call
findMaxSubArray(array, mid, highIndex);
}
if (centerMax >= midHighMax && centerMax >= lowMidMax) {
maxLowIndex = lowCenter;
maxHighIndex = highCenter;
//recursive call
findMaxSubArray(array, lowCenter, highCenter);
}
}//end if even parent array
//else if uneven array
else {
mid = (int) Math.floor(arrayLength / 2);
System.out.println("low: " + lowIndex + " mid: " + mid);
for (int i = lowIndex; i < mid; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowIndex; i < mid; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = lowMidMax = maxEndingHere;
lowIndex = i;
}
}
//end low mid calc
System.out.println("mid+1: " + (mid + 1) + " high: " + highIndex);
for (int i = mid + 1; i <= highIndex; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in mid to high indexes
for (int i = mid + 1; i <= highIndex; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new maximum found
globalMaximum = midHighMax = maxEndingHere;
mid = i;
}
}
//end mid high calc
//calculate maximum contigous array encountered so far in center array
int lowCenter = mid;
int highCenter = highIndex -1;
System.out.println("lowCenter: " + lowCenter + " highCenter: " + highCenter);
for (int i = lowCenter; i < highCenter; i++) {
System.out.print(array[i] + ",");
}
//calculate maximum contigous array encountered so far in low to mid indexes
for (int i = lowCenter; i < highCenter; i++) {
maxEndingHere = maxEndingHere + array[i];
if (maxEndingHere < 0) {
maxEndingHere = 0;
}
if (globalMaximum < maxEndingHere) {
//new max
globalMaximum = centerMax = maxEndingHere;
lowCenter = i;
}
}
//end center calc
//determine which range contains the maximum sub array
//if lowMidMax <= midHighMax and centerMax
if (lowMidMax >= midHighMax && lowMidMax >= centerMax) {
maxLowIndex = lowIndex;
maxHighIndex = mid;
//recursive call
findMaxSubArray(array, lowIndex, mid);
}
if (midHighMax >= lowMidMax && midHighMax >= centerMax) {
maxLowIndex = mid;
maxHighIndex = highIndex;
//recursive call
findMaxSubArray(array, mid, highIndex);
}
if (centerMax >= midHighMax && centerMax >= lowMidMax) {
maxLowIndex = lowCenter;
maxHighIndex = highCenter;
//recursive call
findMaxSubArray(array, lowCenter, highCenter);
}
}//end odd parent array length
}//end outer else array is ok to computed
}//end method
public static void Kadane(int array[]) {
int max_ending_here = 0;
for (int i = 0; i < array.length; i++) {
max_ending_here = Math.max(array[i], max_ending_here + array[i]);
max_so_far = Math.max(max_so_far, max_ending_here);
}
System.out.println("Kadane(int array []): " + max_so_far);
}
[lowIndex,mid)
[mid, highIndex]
[lowCenter, highCenter]
/**
* @author : Yash M. Sawant
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXLENGTH 17
#define MINVALUE -999
int main() {
int i;
int s[MAXLENGTH]; s[0] = 0;
int c[MAXLENGTH] = {0, 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
int pv = 0, p = -1, tp = -1;
for(i = 1 ; i < MAXLENGTH ; i ++) {
printf("%4d ", c[i]);
if(s[i - 1] < pv + c[i]) {
s[i] = pv + c[i];
pv = pv + c[i];
if(tp > p) {
p = tp;
}
} else {
s[i] = s[i - 1];
pv = pv + c[i];
if(pv < 0) {
pv = 0; tp = i;
}
}
}
printf("\n");
for(i = 0 ; i < MAXLENGTH ; i ++) {
printf("%4d ", s[i]);
}
printf("\n");
printf("Max Sub Array = %d and Starts at %d ", s[MAXLENGTH - 1], p);
return 0;
}
// A Divide and Conquer based Java solution
// To find a subarray with the maximum sum
import java.util.Arrays;
import java.util.Scanner;
class MaxSubArray {
private static Result maxCrossingSum(int arr[], int l, int m, int h) {
int sum = 0;
int maxLeft = 0;
int leftSum = Integer.MIN_VALUE;
for (int i = m; i >= l; i--) {
sum = sum + arr[i];
if (sum > leftSum) {
leftSum = sum;
maxLeft = i;
}
}
sum = 0;
int rightSum = Integer.MIN_VALUE;
int maxRight = arr.length - 1;
for (int i = m + 1; i <= h; i++) {
sum = sum + arr[i];
if (sum > rightSum) {
rightSum = sum;
maxRight = i;
}
}
return new Result(maxLeft, maxRight, leftSum + rightSum);
}
private static Result maxSubArray(int[] A, int low, int high) {
if (low == high) {
return new Result(low, high, A[low]);
}
int mid = (low + high) / 2;
Result leftSubArray = maxSubArray(A, low, mid);
Result rightSubArray = maxSubArray(A, mid + 1, high);
Result maxCrossingSubArray = maxCrossingSum(A, low, mid, high);
int leftSum = leftSubArray.sum;
int rightSum = rightSubArray.sum;
int crossSum = maxCrossingSubArray.sum;
if (leftSum > rightSum && leftSum > crossSum) {
return new Result(leftSubArray.low, leftSubArray.high, leftSubArray.sum);
} else if (rightSum > leftSum && rightSum > crossSum) {
return new Result(rightSubArray.low, rightSubArray.high, rightSubArray.sum);
} else {
return new Result(maxCrossingSubArray.low, maxCrossingSubArray.high,
maxCrossingSubArray.sum);
}
}
public static class Result {
public int low;
public int high;
public int sum;
public Result(int low, int high, int sum) {
this.low = low;
this.high = high;
this.sum = sum;
}
}
/* Driver program to test maxSubArray */
public static Result maxSubArray(int[] arr) {
return maxSubArray(arr, 0, arr.length - 1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] arrString = sc.nextLine().split(" ");
int n = arrString.length;
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(arrString[i]);
}
Result result = maxSubArray(arr);
int[] subArray = new int[result.high - result.low + 1];
int j = 0;
for (int i = result.low; i <= result.high; i++) {
subArray[j++] = arr[i];
}
System.out.println(Arrays.toString(subArray));
System.out.println("Sum : " + result.sum);
}
}