1245 最小N个数的和

Posted 微风&细雨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1245 最小N个数的和相关的知识,希望对你有一定的参考价值。

题目就简单的粘贴以下:

题目描述 Description

有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个。

输入描述 Input Description

第一行输入一个正整数N;第二行N个整数Ai 且Ai≤10^9;第三行N个整数Bi,
且Bi≤10^9

输出描述 Output Description

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

样例输入 Sample Input

5

1 3 2 4 5
6 3 4 1 7

样例输出 Sample Output

2 3 4 4 5

此题需要注意的是必须先对两个输入数组进行排序,乱序的数据量N^2太大,数组存不下。然后就是时间复杂度的问题,必须过滤掉一部分数据。对于有序数组a[i],b[j].i*j-1>N的数据是无效的数据。因为已经存在了N个更小的数据。例如当N = 100的时候,i=5,j=20时,(i=1,2,3,4且j<=20) 和( i=5且j<20)的数据一定比a[5]+b[20]小,所以已经存在了100个很小的数据了就不需要比较后续的数据了。完全可以忽略。至于i*j-1的-1是因为i,j这组数据并没有算进去。

因为需要联系堆排序,就使用了堆排序做题:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX_NUM 100005
int heapArr[MAX_NUM*100];
int heapCount = 1;
int a[MAX_NUM];
int b[MAX_NUM];
void insert(int a);
int pop();
int main(){
    int N;
    cin >> N;
    for (int i = 0; i < N; i++){
        cin >> a[i];
    }
    for (int i = 0; i < N; i++){
        cin >> b[i];
    }
    sort(a, a + N);
    sort(b, b + N);
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++){
            if (i*j - 1 > N) break;
            insert(a[i] + b[j]);
        }
    }
    for (int i = 0; i < N; i++){
        cout << pop() << " ";
    }
    cout << endl;
    return 0;
}
void insert(int a){
    heapArr[heapCount] = a;
    int i = heapCount;
    int j = i / 2;
    while (j > 0){
        if (heapArr[i] < heapArr[j]){
            int temp = heapArr[i];
            heapArr[i] = heapArr[j];
            heapArr[j] = temp;
            i = j;
            j = i / 2;
        }
        else{
            break;
        }
    }
    //if (heapCount<MAX_NUM*2) //想当然的进行了数据忽略,然后发现忽略是错误的,对于堆排序本身,叶子节点的数并不代表是很大的数,可能叶子节点的数小于根节点的另一个孩子(次节点的祖先的兄弟节点)。
        heapCount++;
}
int pop(){
    int ans = heapArr[1];
    heapCount--;
    heapArr[1] = heapArr[heapCount];
    int i = 1;
    int j = i * 2;
    int k = j + 1;
    while (j < heapCount){
        if (k < heapCount){
            if (heapArr[j] > heapArr[k]){
                if (heapArr[i] > heapArr[k]){
                    int temp = heapArr[i];
                    heapArr[i] = heapArr[k];
                    heapArr[k] = temp;
                    i = k;
                    j = i * 2;
                    k = j + 1;
                }
                else 
                    break;

            }
            else{
                if (heapArr[i] > heapArr[j]){
                    int temp = heapArr[i];
                    heapArr[i] = heapArr[j];
                    heapArr[j] = temp;
                    i = j;
                    j = i * 2;
                    k = j + 1;
                }
                else 
                    break;
            }
        }
        else{
            if (heapArr[i] > heapArr[j]){
                int temp = heapArr[i];
                heapArr[i] = heapArr[j];
                heapArr[j] = temp;
                i = j;
                j = i * 2;
                k = j + 1;
            }
            else{
                break;
            }
        }
    }
    return ans;
}

犯了一个错误,记录一下

   //if (heapCount<MAX_NUM*2) //想当然的进行了数据忽略,然后发现忽略是错误的,对于堆排序本身,叶子节点的数并不代表是很大的数,可能叶子节点的数小于根节点的另一个孩子(次节点的祖先的兄弟节点)。

 

 

 

 

 

 

以上是关于1245 最小N个数的和的主要内容,如果未能解决你的问题,请参考以下文章

codevs 1245 最小的N个和

1245 最小的N个和

1245 - Harmonic Number (II)---LightOJ1245

最小的N个和 Codevs No.1245

最小的N个和(codevs 1245)

Codevs 1245 最小的N个和