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