算法导论 第四章:分治法(一)
来源:互联网 发布:小米电视怎么设置网络 编辑:程序博客网 时间:2024/06/05 05:09
无论是在生活中还是在计算机科学中,“分而治之”的思想占据着举足轻重的地位,其原理如下:
1)将一个复杂的问题分成若干个相同或相似的子问题
2)递归求解子问题,当子问题规模很小时,可直接求解
3)将所有子问题的解合并,即为原问题的解
1.最大子数组问题(maximum-subarray problem)
即一段非空的,连续的有最大和的一段子数组,如:
若采用暴力求解方法,时间复杂度是Θ(n²)。这里我们用分治法求解,将数组分为两个尽可能等长的子数组,那么最大子数组A[i...j]存在三种情况:
1)完全在子数组A[low...mid]中,满足low ≤ i ≤ j ≤ mid
2)完全在子数组A[mid+1...high]中,满足 mid<i≤j≤high
3)跨越中点(midpoint),满足low ≤ i ≤ mid < j ≤ high
当为情况3时,只需要寻找形如A[i...mid]和A[mid+1...high]的最大子数组,然后连接他们。伪代码如下:
其运行时间为:O(n)。
最大子数组算法的伪代码如下:
运行时间为:
最大子数组问题也可以在线性时间内求解,具体思想参加算法导论(第三版)课后题4.1-5.
三种求解方法的完整代码如下:
#include<iostream>#include<limits.h>using namespace std;int maxSubarr_start; //save the start index of maximum subarray with divid-and-conquer solutionint maxSubarr_end;void Bruteforce_MaxSubarr(int a[],int n,int *res){//Brute-force solutionint maxSum=INT_MIN;for(int i=0;i<n;i++)for(int j=i;j<n;j++) { int temp=0;for(int k=i;k<=j;k++)temp+=a[k];if(temp>maxSum){ maxSum=temp;res[0]=i; //store the start index in array res[0]res[1]=j; //store the end index in array res[1]res[2]=maxSum; //store the maxSum in array res[2]} }}int Crossing_MaxSubarr(int a[],int low,int mid,int high){//case:maximum subarray corssing mid indexint left_sum=INT_MIN;int sum=0;for(int i=mid;i>=low;i--){ sum+=a[i];if(sum>left_sum) {left_sum=sum;maxSubarr_start=i;}}int right_sum=INT_MIN;sum=0;for(int j=mid+1;j<=high;j++){sum+=a[j];if(sum>right_sum){right_sum=sum;maxSubarr_end=j;}}return left_sum+right_sum;}int DC_MaxSubarr(int a[],int low,int high){//divide-and-conquer solutionif(high==low) //only one elementreturn a[low];//divid-and-conquer int mid=(low+high)/2;int left_sum = DC_MaxSubarr(a,low,mid);int right_sum = DC_MaxSubarr(a,mid+1,high);int cross_sum = Crossing_MaxSubarr(a,low,mid,high);if(left_sum>right_sum && left_sum>cross_sum)return left_sum;else if(right_sum>left_sum && right_sum>cross_sum)return right_sum;elsereturn cross_sum;}void LinearTime_MaxSubarr(int a[],int low,int high,int *res){//linear time solution int temp=0;int maxSum=INT_MIN;int max_start,max_end;for(int i=low;i<=high;i++) {temp+=a[i];if(temp>maxSum) //if a[i]<=0 ,refuse{maxSum=temp; max_end=i; //the end index of maximum subarray } if(temp<0)//start at a[i+1]temp=0;}//find the start index of maximum subarraytemp=maxSum;for(int j=max_end;j>=low;j--){temp-=a[j];if(temp==0){max_start=j;break;} }//cout<<"the result:"<<max_start<<" "<<max_end<<" "<<maxSum<<endl;res[0]=max_start;res[1]=max_end;res[2]=maxSum;}int main(){int a[]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};int n=sizeof(a)/sizeof(int);/*-------the maximum-subarray with brute-force solution as following:------*/int *result0;result0=new int[3];Bruteforce_MaxSubarr(a,n,result0);cout<<"Brute-force solution as following:"<<endl;cout<<result0[0]<<" "<<result0[1]<<" "<<result0[2]<<endl;/*---the maximum-subarray with divid-and-conquer solution as following:----*/int result1;cout<<"Divid-Conquer solution as following:"<<endl;result1=DC_MaxSubarr(a,0,n-1);cout<<maxSubarr_start<<" "<<maxSubarr_end<<" "<<result1<<endl;/*-------the maximum-subarry with linear-time solution as following:------*/int *result2;result2=new int[3];cout<<"Linear-time solution as following :"<<endl;LinearTime_MaxSubarr(a,0,n-1,result2);cout<<result2[0]<<" "<<result2[1]<<" "<<result2[2]<<endl;return 0;}运行结果:
第一个数表示最大子数组的起始位置;第二个是表示终止位置;第三个数表示最大子数组和。
0 0
- 算法导论 第四章:分治法(一)
- 算法导论 第四章:分治法(二)
- 算法导论第四章-分治策略-Cpp代码实现
- 算法导论_第四章_分治策略
- 【算法导论】分治法
- 算法导论--分治法
- 算法导论笔记一:算法设计之分治法
- 算法导论:分治法(1)
- 分治法(算法导论Lec3)
- 算法导论第三版第四章 最大子数组和的三种解法(暴力、教材分治法、线性解法)
- 算法导论:分治法(2)
- 算法导论--分治法--P17
- 算法导论之分治法
- 算法导论之分治法
- 算法导论之分治法
- 《算法导论》第四章-思考题(参考答案)
- 算法导论-第四章-分治策略:最大子数组C++实现
- 算法导论第四章笔记
- WinCE程序不能访问sql2000数据库
- 为什么河文档是黑人,而小河看起来却是个白人
- UItableView性能优化
- gcc __attribute__关键字举例之visibility
- UNIX入职理解
- 算法导论 第四章:分治法(一)
- cf NEERC 14 J - Jokewithpermutation
- 自定义列表选择Dialog,适用网络请求数据
- 多层级的makefile编写——递归调用makefile
- Linux命令echo -e -n
- 表达式求值难度3
- Java面试题全集(上)
- PHP unset销毁变量并释放内存
- iOS设计模式——Category