算法設計的幾種思維(編程珠璣算法學習總結)

原題是一個一維模式識別的題:求n個浮點數向量中連續若干個子向量中的最大和。

在書中共討論了四種算法:

第一種算法是最笨的辦法,利用三重循環求出每一個子向量的和,然後求出其中的最大值,其時間複雜度爲O(n3)

int maxvect(int *x,int n)
{
int maxsofar=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
sum=0;
for(int k=i;k<=j;k++)
{
sum+=x[k];
}
maxsofar=max(maxsofar,sum);
}
}
return maxsofar;
}

第二種算法分了兩種,其一是在求x[1…i]時利用x[1…i-1]的值,則減少了一層內循環,第二種是將計算的和的子向量存儲在一個數組中,又可稱爲累積表,這樣每個子向量的和都可由累計表中兩項相減得到。這兩種算法的時間複雜度都是O(n2)

第一種:

int maxvect(int *x,int n)
{
int maxsofar=0;
for(int i=0;i<n;i++)
{
sum=0;
for(int j=0;j<n;j++)
{
sum+=x[j];
maxsofar=max(maxsofar,sum);
}
}
return maxsofar;
}

第二種:

int maxvect(int *x,int n)
{
int maxsofar=0;
int *cumarr=new int[n+1];
cumarr[0]=0;
for(int i=0;i<n;i++)
{
cumarr[i+1]=cumarr[i]+x[i];
}
for(int i=0;i<n;i++)
{
sum=0;
for(int j=i;j<n;j++)
{
sum=cumarr[j+1]-cumarr[i];
maxsofar=max(maxsofar,sum);
}
}
return maxsofar;
}

第三種算法爲分治算法,即分別求兩個子向量的最大和,然後在劃分,最後合併起來,它的時間複雜度爲O(nlogn),在《算法導論》也提到了使用分治算法解這個題的詳細分析過程。其時間複雜度爲O(nlogn)。

int MaxSubSum2(int num[], int start, int end)//O(nlog(n))
{
	int res;
	if (start == end)
	{
		if (num[start] > 0)
			return num[start];
		else
			return 0;
	}
	int mid = (start+end)/2;
	int maxleftsum = MaxSubSum2(num,start,mid);
	int maxrightsum = MaxSubSum2(num, mid+1, end);
	res = maxleftsum > maxrightsum ? (maxleftsum) : (maxrightsum);
	int leftboder = mid;
	int leftbodersum = 0, leftsum = 0;
	while (leftboder >= start)
	{
		leftsum +=num[leftboder];
		if (leftsum > leftbodersum)
			leftbodersum = leftsum;
		leftboder--;
	}
	int rightboder = mid+1;
	int rightbodersum = 0, rightsum = 0;
	while (rightboder <=end)
	{
		rightsum += num[rightboder];
		if (rightsum > rightbodersum)
			rightbodersum = rightsum;
		rightboder++;
	}
	int maxcentersum = rightbodersum + leftbodersum;
	if (maxcentersum > res)
		res = maxcentersum;
	return res;
}

第四種算法掃描算法。它的思想是隻掃描一次,記下遇到的子向量的總和最大的子向量,它的問題是如何有X[0…i-1]擴展爲X[0…i],,它的做法是設立一個結束標誌maxending,它的時間複雜度爲O(n)


int maxvect(int *x,int n)
{
int maxsofar=0;
int maxendnig=0;
for(int i=0;i<n;i++)
{
maxending=max(maxending+x[i],0);
maxsofar=max(maxsofar,maxending);
}
}
return maxsofar;
}

在實際比較幾種算法的運行時間時,我非常直觀的體會的算法對於程序運行性能的影響。我用了10000個數的數組,第四種算法幾乎瞬間完成,而第一種算法就需要若干分鐘,具體性能比較我沒有截圖,不過《編程珠璣》第8章有詳細的對比,有興趣的查看,數據量越大,這種差距越大。

最後書中總結了幾種算法設計的技術:

1.保存中間狀態,避免重複計算。

2.預處理數據,存入一個結構中,如算法2中的累計表,是非常常用的一個手段。

3. 分治算法。

3. 掃描算法。利用X[0…i],擴展到X[0…i+1]


     

点赞