2016年专业408算法题

15 篇文章 0 订阅

0 结果

较优解:
请添加图片描述
最优解:
请添加图片描述

1 题目

请添加图片描述

2 思路

为了使 | n 1 − n 2 | |n_1-n_2| n1n2尽可能小, S 1 − S 2 S_1-S_2 S1S2尽可能的大,则需要使划分的两个子集个数尽量想等,较小元素为一个子集,较大元素为一个子集。

2.1 思路1(较优解:排序)

根据前面的思路,对数组进行快速排序得到升序序列,前一个序列取 0 ∼ n / 2 − 1 0 \sim n/2-1 0n/21,后一个序列取 n / 2 ∼ n − 1 n/2 \sim n- 1 n/2n1

#include <cstdio>
#include <algorithm>

//快排
void Qsort(int A[], int L, int R){
    if(L >= R) return;
    int pivot, i = L, j = R;
    std::swap(A[L], A[rand()%(R - L + 1) + L]);//快排优化
    pivot = A[L];//比较的基准元素
    while(i < j){
        while(i < j && A[j] > pivot) j--;
        while(i < j && A[i] <= pivot) i++;
        if(i < j) std::swap(A[i], A[j]);
    }
    std::swap(A[L], A[i]);
    Qsort(A, L, i - 1);
    Qsort(A, i + 1, R);
}

void ans(int A[], int n){
    Qsort(A, 0, n - 1);
    //输出S1
    for(int i = 0;i < n/2;i++){
        printf("%d ", A[i]);
    }
    printf("\n");
    //输出S2
    for (int i = n/2; i < n; ++i) {
        printf("%d ", A[i]);
    }
    printf("\n");
}

int main(){
    int A[] = {1, 8,3, 6,5, 4,7,2};
    ans(A, sizeof (A)/sizeof (A[0]));
    return 0;
}

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
空间复杂度: O ( l o g n ) O(logn) O(logn)

2.2 思路2(最优解:类快排思想排序)

对数组 A [ 0 ∼ n − 1 ] A[0 \sim n-1] A[0n1]进行类似快速排序的做法,在处理左右区间时只处理可能包含中位数的区间,即如果区间的范围是 [ l , r ] [l, r] [l,r],则只有 l < = n / 2 − 1 < r l<=n/2-1<r l<=n/21<r才会处理该区间。

因为快排的基准元素元素左边一定小于等于基准元素,基准元素右边的一定大于等于基准元素,故如果中位数小于基准元素,则只对右边的部分继续排序,中位数大于基准元素,则只对左边的部分继续排序。含义如下图所示:
请添加图片描述

#include <cstdio>
#include <algorithm>

//快排
void Qsort(int A[], int L, int R,int n){
    if(L >= R) return;
    int pivot, i = L, j = R;
    std::swap(A[L], A[rand()%(R - L + 1) + L]);//快排优化
    pivot = A[L];//比较的基准元素
    while(i < j){
        while(i < j && A[j] > pivot) j--;
        while(i < j && A[i] <= pivot) i++;
        if(i < j) std::swap(A[i], A[j]);
    }
    std::swap(A[L], A[i]);
    //以下内容与原快排内容区别
    if(n/2 - 1 >= L && n/2 - 1 <= i - 1)// n/2-1在左区间范围中
        Qsort(A, L, i - 1, n);//递归处理左区间
    if(n/2 - 1 >= i + 1 && n/2 - 1 <= R)
        Qsort(A, i + 1, R, n);
}

void ans(int A[], int n){
    Qsort(A, 0, n - 1, n);
    //输出S1
    for(int i = 0;i < n/2;i++){
        printf("%d ", A[i]);
    }
    printf("\n");
    //输出S2
    for (int i = n/2; i < n; ++i) {
        printf("%d ", A[i]);
    }
    printf("\n");
}

int main(){
    //int A[] = {4, 1, 8,6, 3, 2, 5, 7};
    int A[] = {3,4,2,1,7,8,5,6};//最优解测试序列
    ans(A, sizeof (A)/sizeof (A[0]));
    return 0;
}

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( l o g n ) O(logn) O(logn)

附录

408历年真题算法题解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

繁星蓝雨

如果觉得文章不错,可以请喝咖啡

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

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

打赏作者

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

抵扣说明:

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

余额充值