2016年考研数据结构算法题(递归+非递归)

已知由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;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值