概述
已知由n(n>=2)个正整数构成的集合A ,将其划分成两个不相交的子集A1和A2,元素个数分别为n1和n2,A1和A2中元素之和分别为S1和S2。设计一个尽可能高效的划分算法,满足|n1-n2|最小且|S1-S2|最大。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
3)说明你所设计算法的平均时间复杂度和空间复杂度。
思路
题目给了关键字划分,可知要用分治的算法,需要将小的划分到左边,大的划分到右边,回想一下可以发现与我们经常接触到的快速排序算法有异曲同工之妙,此处可以优化的是不需要全部排序,只需要找到中间位置后返回就行
快速排序
该方法的基本思想是:
- 1.先从数列中取出一个数作为基准数。
- 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
- 3.再对左右区间重复第二步,直到各区间只有一个数。
递归算法如下:
void QuickSort(int a[],int low, int high,int n){
//找到中间位置就满足要求了
if(low == n/2 ){
return;
}
if(low >= high){
return;
}
int low0 = low;
int high0 = high;
//快速排序逻辑
int key = a[low];
while(low < high)
{
while(low < high && a[high] >= key) --high;
if(low != high) a[low] = a[high];
while(low < high && a[low] <= key ) ++low;
if(low != high) a[high] = a[low];
}
a[low] = key;
// if(i == n/2-1) return ;
QuickSort(a,low0,low-1,n);
QuickSort(a,low+1,high0,n);
}
非递归算法如下:
//非递归
int Partition(int a[],int low,int high){
int i =low,j=high;
int povit=a[low];
while(i<j){
while(i<j&&a[j]>=povit)
j--;
if(i != j) {
a[i] = a[j];
}
while(i<j&&a[i]<=povit)
i++;
if(i != j){
a[j] = a[i];
}
}
a[i]=povit;
return i;
}
int solution(int a[], int n){
int low =0,high=n-1;
bool flag = true;
while(flag){
int i = Partition(a,low,high);
if(i==n/2-1){
flag = false;
}
else if(n/2-1>i){
low = i+1;
} else{
high = i-1;
}
}
int s1 = 0,s2=0;
for(int i=0;i<n/2-1;i++){
s1 +=a[i];
}
for(int j=n/2;j<n;j++){
s2+=a[j];
}
return s2-s1;
}
最后
以上就是贪玩蜜蜂为你收集整理的2016年考研数据结构算法题(递归+非递归)的全部内容,希望文章能够帮你解决2016年考研数据结构算法题(递归+非递归)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复