队列优先

题目背景

题目描述

       有两个长度都是 N 的序列 A 和 B ,在 A 和 B 中各取一个数相加可以得到 N2 个和,求这 N2 个和中最小的 N 个。

输入格式

       第一行一个正整数 N ,满足 1≤N≤1000000
       第二行 N 个整数 Ai ,满足 Ai≤109
       ​第三行 N 个整数 Bi ,满足 Bi≤109

输出格式

       输出仅一行,包含 N 个整数,从小到大输出这 N 个最小的和,相邻数字之间用空格隔开。

输入输出样例

输入样例

3
2 6 6
1 4 8

输出样例

3 6 7

AC代码与思路

       两个数组输入的数不保证有序

优先队列

       生成一个长度为N的优先队列,该队列由A[i]+B[0]组成(i=0,1,2……,N-1)。若A[ i ]+B[ j ]被取出队列,将A[ i ]+B[ j+1 ]放入队列。按此取出N个元素,该N个元素即为最小的N个元素。

#include <iostream>
#include <queue>
#include <algorithm>

using namespace std;

#define MaxSize 1000010

typedef struct SumWithFactor
{
    int FactorANo;
    int FactorBNo;
    int Sum;

    //优先队列默认大顶堆,改变"<"定义,使其变成小顶堆
    bool friend operator<(SumWithFactor Sum1, SumWithFactor Sum2)
    {
        return Sum1.Sum > Sum2.Sum;
    }
} SumWithFactor;

int main()
{
    int n;
    int NoA, NoB;
    int NumSetA[MaxSize] = {0}, NumSetB[MaxSize] = {0};

    SumWithFactor Temp;
    priority_queue<SumWithFactor> SumList;

    //关闭流同步
    ios::sync_with_stdio(false);
    cin >> n;

    for (int i = 0; i < n; ++i)
        cin >> NumSetA[i];

    for (int i = 0; i < n; ++i)
        cin >> NumSetB[i];

    //排序
    sort(NumSetA, NumSetA + n);
    sort(NumSetB, NumSetB + n);

    //生成一个长度为n的优先队列
    //该队列由A[i]+B[0]组成(i=0,1,2……,n-1)
    for (int i = 0; i < n; ++i)
    {
        Temp.FactorANo = i;
        Temp.FactorBNo = 0;
        Temp.Sum = NumSetA[i] + NumSetB[0];
        SumList.push(Temp);
    }

    //若A[i]+B[j]被取出队列,将A[i]+B[j+1]放入队列
    //按此取出n个元素,该n个元素即为最小的n个元素
    for (int i = 0; i < n; ++i)
    {
        Temp = SumList.top();
        cout << Temp.Sum << " ";    //注意输出格式
        SumList.pop();
        ++Temp.FactorBNo;
        Temp.Sum = NumSetA[Temp.FactorANo] + NumSetB[Temp.FactorBNo];
        SumList.push(Temp);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值