《算法导论(第三版)》第四章 分治策略 第1节 提到的一些算法
《算法导论(第三版)》第四章 分治策略 第1节 提到的最大子数组求解算法。包含了分治策略算法、暴力求解算法、根据求解规模分别调用分治策略算法,暴力求解算法、以及出现空集情况的实现。
/**
* 《算法导论(第三版)》第四章 分治策略 第1节 提到的一些算法
**/
public class Alg_04_01{
public static void main(String[] args) {
Alg_04_01_1.mehtod();
Alg_04_01_2.mehtod();
Alg_04_01_3.mehtod();
Alg_04_01_4.mehtod();
Alg_04_01_5.mehtod();
}
}
/**
* 《算法导论(第三版)》第四章 分治策略 第1节 提到最大子数组的分治策略算法
***/
class Alg_04_01_1{
public static void mehtod() {
System.out.println("《算法导论(第三版)》第四章 分治策略 第1节 提到最大子数组的分治策略算法Alg_04_01_1.mehtod:");
int[] arr=new int[]{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
int[] ret=alg(arr, 0, arr.length-1);
for(int i=0;i<ret.length;i++) {
System.out.print(ret[i]+",");
}
System.out.println();
System.out.println("《算法导论(第三版)》第四章 分治策略 第1节 提到最大子数组的分治策略算法(全部为负数的情况)Alg_04_01_1.mehtod:");
arr=new int[]{-1,-3,-25,-1,-3,-16,-23,-1,-1,-7,-1,-5,-22,-1,-4,-7};
ret=alg(arr, 0, arr.length-1);
for(int i=0;i<ret.length;i++) {
System.out.print(ret[i]+",");
}
System.out.println();
}
/**
* @return [0]-low,[1]-high,sum-[2]
* */
public static int[] alg(int[] arr,int low,int high) {
if(low==high) {
return new int[] {low,low,arr[low]};
}else {
int mid=(low+high)/2;
int[] lret=alg(arr,low,mid);
int[] rret=alg(arr,mid+1,high);
int[] mret=alg1(arr,low,mid ,high);
if(lret[2]>rret[2]&&lret[2]>mret[2]) {
return lret;
}else {
if(rret[2]>mret[2]) {
return rret;
}else {
return mret;
}
}
}
}
/**
* @return [0]-low,[1]-high,sum-[2]
* */
public static int[]alg1(int[] arr,int low,int mid,int high){
int left_sum=arr[mid];
int max_left=mid;
int sum=0;
for(int i=mid;i>=low;i--) {
sum+=arr[i];
if(sum>=left_sum) {
left_sum=sum;
max_left=i;
}
}
int right_sum=arr[mid+1];
int max_right=mid+1;
sum=0;
for(int i=mid+1;i<=high;i++) {
sum+=arr[i];
if(sum>=right_sum) {
right_sum=sum;
max_right=i;
}
}
return new int[]{max_left,max_right,left_sum+right_sum};
}
}
/**
* 《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-2 提到最大子数组的 暴力求解算法
***/
class Alg_04_01_2{
public static void mehtod() {
System.out.println("《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-2 提到最大子数组的 暴力求解算法Alg_04_01_2.mehtod:");
int[] arr=new int[]{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
int[] ret=alg(arr);
for(int i=0;i<ret.length;i++) {
System.out.print(ret[i]+",");
}
System.out.println();
}
public static int[] alg(int[] arr) {
int[] ret=new int[] {0,0,arr[0]};
for(int i=0;i<arr.length;i++) {
int sum=0;
for(int j=i;j<arr.length;j++) {
sum+=arr[j];
if(sum>ret[2]) {
ret[0]=i;
ret[1]=j;
ret[2]=sum;
}
}
}
return ret;
}
}
/**
* 《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-3 提到最大子数组的 根据性能交叉点分别调用暴力求解法和分治策略算法<br>
* 分治策略算法复杂度为t=(n+1)*log(2,n)<br>
* 暴力求解算法复杂度为t=(n+1)*n/2<br>
* 令n=1,2,2^2,2^3,2^4<br>
* 得到分治策略算法时间为t=1,3,10,24,68<br>
* 得到暴力求解算法时间为t=1,3,10,36,136<br>
* 性能交叉点在[2^3~2^4]。
***/
class Alg_04_01_3{
public static void mehtod() {
System.out.println("《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-3 提到最大子数组的 根据性能交叉点分别调用暴力求解法和分治策略算法Alg_04_01_3.mehtod:");
int[] arr=new int[]{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
int[] ret=alg(arr, 0, arr.length-1);
for(int i=0;i<ret.length;i++) {
System.out.print(ret[i]+",");
}
System.out.println();
}
/**
* @return [0]-low,[1]-high,sum-[2]
* */
public static int[] alg(int[] arr,int low,int high) {
if(high-low<=8) {
int[] ret=new int[] {low,low,arr[low]};
for(int i=low;i<=high;i++) {
int sum=0;
for(int j=i;j<=high;j++) {
sum+=arr[j];
if(sum>ret[2]) {
ret[0]=i;
ret[1]=j;
ret[2]=sum;
}
}
}
return ret;
}else {
int mid=(low+high)/2;
int[] lret=alg(arr,low,mid);
int[] rret=alg(arr,mid+1,high);
int[] mret=Alg_04_01_1.alg1(arr,low,mid ,high);
if(lret[2]>rret[2]&&lret[2]>mret[2]) {
return lret;
}else {
if(rret[2]>mret[2]) {
return rret;
}else {
return mret;
}
}
}
}
}
/**
* 《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-4 假定修改最大子数组的问题的定义,允许结果为空子数组,其和为0。你应该如何修改现有的算法,使他们能允许空子数组的为最终结果?<br>
* 可在数组末尾加入元素0。当返回的起止下标均为元素0的下标时时,则为空集。
***/
class Alg_04_01_4{
public static void mehtod() {
System.out.println("《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-4 允许返回空集的情况Alg_04_01_4.mehtod");
int[] arr=new int[]{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7,0};//数组末尾加入了0
int[] ret=Alg_04_01_1.alg(arr, 0, arr.length-1);
if(ret[0]==arr.length-1&&ret[1]==arr.length-1) {
System.out.print("空集");
}else {
for(int i=0;i<ret.length;i++) {
System.out.print(ret[i]+",");
}
}
System.out.println();
System.out.println("《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-4 允许返回空集的情况Alg_04_01_4.mehtod");
arr=new int[]{-1,-3,-25,-1,-3,-16,-23,-1,-1,-7,-1,-5,-22,-1,-4,-7,0};//数组末尾加入了0
ret=Alg_04_01_1.alg(arr, 0, arr.length-1);
//ret=Alg_04_01_2.alg(arr);
ret=Alg_04_01_3.alg(arr, 0, arr.length-1);
if(ret[0]==arr.length-1&&ret[1]==arr.length-1) {
System.out.print("空集");
}else {
for(int i=0;i<ret.length;i++) {
System.out.print(ret[i]+",");
}
}
System.out.println();
}
}
/**
* 《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-5 已知A【1,j】的最大子数组,求A【1,j+1】的最大子数组要求算法在线性时间范围内。<br>
* 暴力求解算法Alg_04_01_2是这个思想
*
***/
class Alg_04_01_5{
public static void mehtod() {
System.out.println("《算法导论(第三版)》第四章 分治策略 第1节 练习题4.1-5 已知A【1,j】的最大子数组,求A【1,j+1】的最大子数组Alg_04_01_5.mehtod:");
int[] arr=new int[]{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
int[] ret=alg(arr);
for(int i=0;i<ret.length;i++) {
System.out.print(ret[i]+",");
}
}
public static int[] alg(int[] arr) {
int[] ret=new int[] {0,0,arr[0]};
for(int i=0;i<arr.length;i++) {
if(i>0) {
System.out.println("已知a[0,"+(i-1)+"]的最大子数组为a["+ret[0]+","+ret[1]+"]");
}
int sum=0;
for(int j=i;j>=0;j--) {
sum+=arr[j];
if(sum>ret[2]) {
ret[0]=j;
ret[1]=i;
ret[2]=sum;
}
}
System.out.println("求得a[0,"+i+"]的最大子数组为a["+ret[0]+","+ret[1]+"]");
}
return ret;
}
}