zzbcoder

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  14 随笔 :: 1 文章 :: 0 评论 :: 2876 阅读

假设n为偶数,现在要求将n个数分成两个等规模的集合s1,s2,并且使得s1中元素的和减去s2中元素之和的差是最大值。请写算法,并分析时间性能。

看到这个题目,直观理解,我想到了直接把这个数组中的数字进行排序,元素之和的差最大,也当然就是排序过后的前一半和后一半元素差值最大,显然,一个快速排序可以满足这个要求。快排的时间复杂度为O(nlgn)

考虑到分治思想,该如何进行优化。例如二分搜索的基本思想是,将n个元素分成两个等规模的集合s1,s2,取a[n/2]与x相比较。如果x=a[n/2],则找到x,终止算法;如果x=a[n/2],则在数组a的左半部分继续搜索x;如果x=a[n/2],则在右边寻找。在最坏情况下,while循环被执行了O(logn)次。循环体内运算需要O(1)时间,因此整个算法在最坏情况下的时间复杂性为O(logn)。

利用快速排序的划分思想,设正整数集合为数组S,划分为前半个数组S1,后半个数组为S2,若第一次划分的轴值是中位数,则返回;若不是继续划分中位数所在的部分。

考虑快排中的分治思想

如果s1 (大的数集)的的个数大于n/2

将(i<=n/2-loW-1)个最小的数排到后面

如果s1 (大的数集)的的个数小于n/2

将s2 (小的数集) n/2-low-1排到前面

将排好的数组的前n/2个数赋值给s1

将排好的数组的后n/2个数赋值给s2

#include <iostream>

#include <stdlib.h>

#include <math.h>

using namespace std;

const int n = 8;

void partions(int a[], int low, int high)

{ //进行一趟快排

    int key = a[low];

    a[0] = a[low];

    while (low < high)

    {

        while (low < high && a[high] <= key)

        {

            --low;

            a[low] = a[high];

        }

        while (low < high && a[low] >= key)

        {

            ++low;

            a[high] = a[low];

        }

    }

    a[low] = key;

    //如果s1(大的数集)的的个数大于n/2

    if (low >= n / 2)

    {

        for (int i = 0; i <= n / 2 - low - 1; ++i)

        {

            for (int j = 0; j < n - 1; ++j)

            {

                if (a[j] < a[j + 1])

                {

                    int temp = a[j];

                    a[j] = a[j + 1];

                    a[j + 1] = temp;

                }

            }

        }

    }

    //如果s1(大的数集)的的个数小于n/2 else

    else

    {

        for (int i = 0; i <= n / 2 - low - 1; ++i)

        {

            for (int k = n - 1; k < n - i; ++k)

            {

                if (a[k] > a[k - 1])

                {

                    int temp1 = a[k];

                    a[k] = a[k - 1];

                    a[k - 1] = temp1;

                }

            }

        }

    }

}

int main()

{

    int a[n] = {1, 3, 5, 9, 6, 0, -11, -8};

    partions(a, 0, n - 1);

    for (int i = 0; i < n; ++i)

    {

        if (i < 4)

        {

            cout << "属于子集s1的" << endl;

            cout << "属于子集s2的" << endl;

            cout << a[i] << endl;

        }

    }

    return 0;

}

时间复杂度O(n),空间复杂度O(1)。

posted on   码dao成功  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示