算法题(二)--划分数组求和

题目:已知有一个集合A,A内的元素大于等于0,现将其分成两个没有交集的子集A1和A2, 元素个数分别是n1和n2, A1和A2中元素的和分别是S1和S2,利用尽可能高效的划分算法,满足|n1-n2|最小且|S1-S2|最大。

设计思路
根据题目可知, 让|n1-n2|=0或1时满足|n1-n2|最小, 若满足|S1-S2|最大需要让S1中元素都是数组中较小的, S2中元素都是数组中较大的。
可以利用快速排序的方式, 根据枢轴所在的位置i判断
当i=n/2时, 分组完成
当i<n/2时, i位置的元素及其之前元素属于A1, 继续对i之后的元素进行划分
当i>n/2时, i位置的元素及其之后元素属于A2, 继续对i之前的元素进行划分

代码实现
主要位置代码

int QuickSort(int a[], int n){
    // pivotKey: 存储分枢轴,
    // low最左侧元素, low0标记low在改变前的位置
    // high最右侧元素, high0标记high在改变前的位置
    // flag作为循环的判断, 当low的值n/2时, flag=0跳出循环
    // k数组长度的一半
    int pivotKey, low=0,low0=0, high=n-1, high0=n-1, flag=1, k=n/2;
    int s1=0, s2=0;
    while (flag){ // 当low=k-1 也就是n/2-1时,flag=0
        pivotKey=a[low]; // 选择枢轴
        // 利用分治思想, 根据枢轴分割枢轴
        while (low<high){
            while (low<high && a[high]>=pivotKey){
                --high;
                if (low!=high){
                    a[low]=a[high];
                }
            }
            while (low<high && a[low]<=pivotKey){
                ++low;
                if (low!=high){
                    a[high]=a[low];
                }
            }
        }
        a[low]=pivotKey; // 把分割值放到对应的位置
        // 判断此时low的位置是否处于n/2的位置
        if (low==k-1){ // 枢轴是n/2时,分割结束
            flag=0; //
        } else {
            if (low<k-1){
                low0=++low;
                high=high0;
            } else {
                low=low0;
                high0=--high;
            }
        }
    }
    // 数组前一半的值相加
    for (int i = 0;  i< k; i++) {
        s1+=a[i];
    }
    // 数组后一半的值相加
    for (int i = k;  i< n; i++) {
        s2+=a[i];
    }
    return s2-s1;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y_努力_strive

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值