已知由n(n>=2)个正整数构成的集合A ,将其划分成两个不相交的子集A1和A2,元素个数分别为n1和n2,A1和A2中元素之和分别为S1和S2。设计一个尽可能高效的划分算法,满足|n1-n2|最小且|S1-S2|最大。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
3)说明你所设计算法的平均时间复杂度和空间复杂度。
思想:|n1-n2|最小且|S1-S2|最大,也就是说A1和A2中的元素个数尽可能接近,并且两个表中的元素差距尽可能大。也就意味着,元素尽可能相等,但是A1中元素尽可能小,A2中元素尽可能大。通过快速排序,可以将表划分成左表小,右表元素大的两个表。(块间有序,内部可以无序)。
划分后,i=(n/2)-1;向下取整,表示划分完成,且左表为0.....i,右表为i+1.........n-1)
i<(n/2)-1;向下取整,继续对右边进行处理
i>(n/2)-1;向下取整,继续对左边进行处理
代码:
int divite(int A[],int n){
int left=0,right=n-1;
while(true){
int low=left,high=righ;//用来记录开始时的left和right
int pivot=A[left];//枢纽
while(left<right){
//处理右侧
while(left<righ&&A[righ]>=pivot){
--righ;
}
A[left]=A[right]
//处理左侧
while(left<righ&&A[left]<=pivot){
++left;
}
A[righ]=A[left];
}
A[left]=pivot;//处理枢纽
//看本次枢纽所在的情况
if(left==n/2-1){
break;
} else if(left<n/2-1){
left++;
right=high;
}else{
righ--;
left=low;
}
}
return left;//划分完成,left为A1中最后一个元素
}
时间复杂度O(n),空间复杂度O(1)。