《算法导论》学习日记(二)

分治思想

求最大连续子数组和:

方法一:暴力法:

暴力法求最大和,就是利用循环将一个数组的无数组合可能性的和都求出来,进行比较,求出当下最大和的最大值
如代码中的第一个大循环,就是以i为起始,以j为结尾的元素下标,然后将所有以i为开头,以j为结尾的的数组的组合都求出来,算出来一个最大值,然后,以i+1,为开头,继续进行,直到所有的都算出来为止
比如说一个数组arr[1,2,-3],如图:
《算法导论》学习日记(二)_第1张图片


import java.util.Scanner;

public class baoli {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int k=sc.nextInt();
		//第一行输入原始数组的长度
		int[] arr=new int[k];
		//确定数组的长度
		for(int i=0;icur) {
					//arrsum达到最大值以后,将这个数值赋给cur
					cur=arrsum;
					//在当前停下的,就是起始值
					left=i;
					right=j;
				}
			}
		}
		
		for(int l=left;l<=right;l++) {
			max+=arr[l];
		}
		return max;
		
	}
}


方法二:神奇的方法

这个是从B站上学到的,附上链接,这个方法是设定两个值,一个cur,一个max,cur用来不断移动累加取得当前的最大值,并且当cur为负数的时候就重置为0,而max则是初始为最小值,也就是MIN_VALUE,之后与cur不断比较,存储cur的最大值,而最后,max的值就是最大和。
比如说一个数组arr[1,2,3,-4,-5,6,7],如图:

《算法导论》学习日记(二)_第2张图片

import java.util.Scanner;
public class zishuzu {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int k=sc.nextInt();
		//第一行输入原始数组的长度
		int[] arr=new int[k];
		//确定数组的长度
		for(int i=0;i

方法三:分治法:

分治法是《算法导论》本章很重要的一个知识点,但是。。。嗯。。。菜鸡发现道理我都懂,代码不会写,后参考大神代码理解。
分治法求最大和就是寻找到最大连续子数组,只要找到这个最大连续子数组,就可以求和了,而最大连续子数组的位置,按照分治思想有三种可能性:1.在原始数组的左端部分,2.在原始数组的中间位置,3.在原始位置的右部分
所以从中间位置划分,开始游览,左边部分与右边部分的最大和的,而中间位置其实就是左右部分的最大值的相加, 递归相加即可。
比如说一个数组:arr[]={1,2,-3,-4,-5,6,7,-8,-9,-10},如图:
《算法导论》学习日记(二)_第3张图片


import java.util.Scanner;

public class fenzhi {
	//三个部分进行比较
	public static int max3(int a, int b ,int c) {
        int max=a;
        if(b>max) {
            max=b;
        }
        if(c>max) {
            max=c;
        }
        return max;
    }
    
    public static int findmaxSubSum(int[] arr,int left, int right) {
        int maxLeftSum,maxRightSum; //左边和右边最大和
        int maxLeftBorderSum, maxRightBorderSum; //含中间边界的左右部分最大和
        int leftBorderSum, rightBorderSum; //含中间边界的左右部分当前和的值
        int i,center;
        //如果左右下标相等,左右相加的时候,返回一个左边的
        if(left == right) {          
                return arr[left];         
        }
        
        center = (left + right)/2;
        //中间值,从这里开始
        
        //找出左部最大值
        maxLeftBorderSum =0;
        leftBorderSum =0;
        for(i=center;i>=left;i--) {
            leftBorderSum += arr[i];
            //让左边部分定义的这个和不断进行累加
            if(leftBorderSum > maxLeftBorderSum) {
            	//并将最大值赋给
                maxLeftBorderSum = leftBorderSum;
            }
        }
        
        //找出右部最大值
        maxRightBorderSum =0;
        rightBorderSum =0;
        for(i=center+1;i<=right;i++) {
            rightBorderSum +=arr[i];
            if(rightBorderSum>maxRightBorderSum) {
                maxRightBorderSum = rightBorderSum;
            }
        }
        
        //递归求左右部分最大值
        maxLeftSum =findmaxSubSum(arr, left, center);
        maxRightSum = findmaxSubSum(arr, center+1, right);
        //左部分,右部分,中间值跨界部分
        return max3(maxLeftSum, maxRightSum, maxLeftBorderSum+maxRightBorderSum);
    }
    
    public static int maxSubSum(int arr[],int len) {
        return findmaxSubSum(arr, 0, len-1);
        //数组的长度、数组左部分,即left,数组右部分,即right
    }
    
    public static void main(String[] args) {
    	Scanner sc=new Scanner(System.in);
		int k=sc.nextInt();
		//第一行输入原始数组的长度
		int[] arr=new int[k];
		//确定数组的长度
		for(int i=0;i

你可能感兴趣的:(java,算法)