已知由 n(n≥2) 个正整数构成的集合 A={ak|0≤k<n} ,将其划分为两个不相交的子集 A1 和 A2 ,元素个数分别是 n1 和 n2 , A1 和 A2 中元素之和分别为 S1 和 S2 。设计一个尽可能高效的划分算法,满足 |n1−n2| 最小且 |S1−S2| 最大。要求:
⑴ 给出算法的基本设计思想。
⑵ 根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
⑶ 说明你所设计算法的时间复杂度和空间复杂度。
算法描述
①先确定划分区间,最小的n/2个在一个区间,可保证ℓs1-s2|最大,同时|n1-n2|最小
②反向冒泡排序,mid=n/2为排序轮次,从后往前比较,把最小的前n/2个元素选出来即可,不用全都排序
③输出结果
时间:o(n^2)
空间:o(1)
#include <iostream>
using namespace std;
int bubble(int a[],int n)
{
int mid=n/2;//记录排序轮次,也是最后要冒出来的最小的前mid个元素
for(int i=0;i<mid;i++)//控制轮次
{
cout<<"轮次"<<i<<endl;
for(int j=n-1;j>i;j--)//控制比较,从后往前比较,最小的冒前面
{
if(a[j]<a[j-1])
swap(a[j],a[j-1]);
}
}
int s1=0,s2=0;
for(int i=0;i<mid;i++)s1+=a[i];
for(int j=mid;j<n;j++)s2+=a[j];
return abs(s1-s2);
}
int main() {
int arr[] = { 61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62 };
int len = (int) sizeof(arr) / sizeof(*arr);
cout<<bubble(arr, len)<<endl;
for (int i = 0; i < len; i++)
cout << arr[i] << ' ';
cout << endl;
return 0;
}