算法初步--求最大子数组和【暴力|优化枚举|贪心 】求解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29963323/article/details/78449516

今天要把算法联系提到日程上了,就从最简单的算法开始学习。介绍一下求解的过程。

首先问题是这样的,给定数组a[1…n],求最大子数组和,即找出1<=i<=j<=n,使a[i]+a[i+1]+…+a[j]最大,求最大子数组和。

题意:int[] arr = {-2,-1,-3,4,-1,2,1,-5,4}; 比如有这样一个数组,求这个数组的子数组加起来的值最大。这里给出三种解法,时间复杂度分别为 O(N^3) O(N^2) O(N),由简单的思路开始,第一种解法,暴力,全部枚举出来:

暴力:

		int max = 0;
		int[] arr = {-2,-1,-3,4,-1,2,1,-5,4};
		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr.length;j++) {
				int sum = 0;
				
				for(int k=i;k<j;k++) {
					sum = sum+(arr[k]);
				}
				if(max < sum) {
					max = sum;
				}
			}
		}
		System.out.println(max);

这里求解这道题用了三层循环,我们主要看最内层循环,这里i和j分别是起始位置和终止位置,遍历出每个sum,然后找到最大的那个,就是数组子数组加起来的值最大。显然,这里的时间复杂度为O(N^3),虽然能算出结果,为6,但是明显是超时的,下面给出第二个解法,发最内层循环去掉。


优化枚举:

int max = 0;
		int[] arr = {-2,-1,-3,4,-1,2,1,-5,4};
		for(int i=0;i<arr.length;i++) {
			int sum = 0;
			for(int j=i+1;j<arr.length;j++) {
				sum = sum+(arr[j]);
				if(max < sum) {
					max = sum;
				}
			}
		}
		System.out.println(max);
	}
}
这里,j的值肯定比i的值大,因为要在一个区间内。所以这是j是从i+1开始的,枚举出每个区间的值,这样最后一个数之前的全部和就只算了一遍,这就简化了,就能算出i到j区间内相加得到的最大值。显然,这个事件复杂度为O(N^2),在OJ系统中,也是超时的,不能通过的,下面给出一个算法,事件复杂度为O(N)的


贪心:

起初,这个解法并不知道叫贪心。是这样的,我们可以把从i到j区间相加得到最大转化为  前j个数相加得到的值减去前i个数相加得到的值,找到最大值就可以了。这样就变成让j固定不动,找出前i个值相加得到的最小值就可以了。我们定义三个变量  si:前i个值得和,sj:前j个值得和,minSi:前i个值最小的和。


  		int max = 0;
		int si = 0;//前i个值得和
		int sj = 0;//前j个值得和
		int minSi = 0;//前i个值最小的值
		int[] arr = {-2,-1,-3,4,-1,2,1,-5,4};
		//固定下来
		for(int i=0;i<arr.length;i++) {
			sj += arr[i];//前j个值
			if(minSi > si) {
				minSi = si;
			}
			//前j个值减去前i个值最小和
			if(sj - minSi > max) {
				max = sj - minSi;
			}
			
			si+=arr[i];
		}
		System.out.println(max);

这样的想法还好想点。若想变成网上的一些贪心的算法,比如

int[] arr = {-2,-1,-3,4,-1,2,1,-5,4};
		int ans = -34324324;
		int sum = 0;//si - minSi
		for(int i=0;i<arr.length;i++) {
			sum += arr[i];
			if(sum > ans) {
				ans = sum;
			}
			if((sum)< 0) {
				sum = 0;
			}
		}
		System.out.println(ans);

这里的代码就是由这段代码上面的转化过来的。我们可以采用代码替换,用 sum = si-minSi,si和si是一样的,这样一步步替换掉就可以了。最后替换是,sum与minSi无关,于是sum就是随着si的变化而变化的,所以si+=arr[i] 可以转化为 sum+=arr[i].还有先加后加问题,把sum+=arr[i]放在后面和放在前面的问题,sum+arr[i]变为sum等等。转化之后就能看出来了。


此文章不建议作为参考,仅供自己查阅。比较乱。。。。。作为笔记看。。。。。





猜你喜欢

转载自blog.csdn.net/qq_29963323/article/details/78449516
今日推荐