《编程珠玑》笔记一

编程珠玑。关于寻找最大相加连续自串

输入 31 -41 59 26 -53 58 97 -93 -23 84

输出187 

原因 59 26 -53 58 97相加的和为187


算法分治算法。

分治算法并不稀奇,快速排序,归并排序就是一个典型的分治算法。

分治算法总是和递归有着离不开的关系。分治算法最简单的问题已经是一个可直接求解的问题。比如排序分治到最后就剩一个数,那么一个数一定是已经排序好的。快速排序的一个改进方法就是在分治到子串大小为32左右的时候就调用插入排序算法。因为插入排序算法在32个数一下的时候比快速排序要快一点。


分治算法的编程格式


return_T fun( args....)

1确定递归结束条件,如子串个数为零,左索引大于右索引等等

2本子串的过程,如划分字串等等。。这里要注意划分分割点的归属问题,只能在一个子串中。如源码所示

3进行分治。对子串调用递归




package test;


public class test
{
	
	public static int findMax(int[]arr,int l,int r)
	{
		
		if(l>r) return 0;
		if(l==r) return arr[l]>0?arr[l]:0;
		int m=(l+r)/2;
		
		int lmax=0;
		int sum=0;
		
		for(int i=m;i>=l;i--)
		{
			sum+=arr[i];
			if(sum>lmax)
			{
				lmax=sum;
			}
		}
		
		int rmax=0;
		sum=0;
		for(int i=m+1;i<=r;i++)//这里一定要是m+1,因为我们已经把m放到前一个子串中
		{
			sum+=arr[i];
			if(sum>rmax)
			{
				rmax=sum;
			}
		}
		int sidemax=Math.max(findMax(arr, l,m), findMax(arr,m+1/*<span style="font-family: Arial, Helvetica, sans-serif;">这里一定要是m+1,因为我们已经把m放到前一个子串中*/</span>,r));
		int middlemax=rmax+lmax;
		return  Math.max(sidemax, middlemax);
		
	}
	
	public static void main(String []args)
	{
		int arr[]={31,-41,59,26,-53,58,97,-93,-23,84};
		//int arr[]={59,26,-53,58,97};
		System.out.println(findMax(arr, 0, arr.length-1));
	}
	
};


这个算法的执行效率是nlog(n)。。

还有一个类似于动态规划算法。这个算法可以在线性时间内解决这个问题


假设我们已经得出了[0  i-1]的解maxsofar.如何把这个解拓展到[0 i]呢?

1在[0 i-1]中带有i-1元素的最长子串.可能是1到i-1 也可能是 2到 i-1 也可能 什么都没有,那就是0.我们定义为maxendinghere。

[0 i]的maxendinghere=[0 i-1]的maxendinghere +arr[i] 和0 的中大者。

可以想象,如果i-1的maxendinghere +arr[i]是正的,那么说明前面的子串(包括x[i])还有可能成为最大子串,说白了,还可能对后来的构建最大子串有贡献。

如果是负的,说明前面子串(包括x[i])已经是不可能是最大子串了。因为他是负的,如果子串不截断,那么他会使子串的值减小。最好就是一刀切断,以绝后患。新的子串重新开始构造

2[0 i]的最优解只可能从两个地方产生,a原来的最优解。bmaxendinghere +arr[i]。


给出伪代码

maxsofar=0

maxendinghere=0

for i=[0,n)//这里没有n

    maxendinghere=max (maxdinghere+x[i],0)

    maxsofar=max(maxsofar,maxendinghere)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值