演算法之求兩個陣列各任意一位相加和組成的新陣列中的前k位
阿新 • • 發佈:2019-01-03
輸入時兩個整數陣列,他們任意兩個數的和又可以組成一個數組,求這個和中前k個大的數。
如題,首先想到的暴力排序,把兩個陣列能相加得所有數放入一個新的陣列,然後用各種排序,假設第一個陣列長m,第二個陣列長n。若用快速排序或堆排序等較快的排序。時間複雜度為o((log2(m+n))*(m+n)),空間複雜度為o(m+n)。顯然我們只需要前k個大的數,並不需要儲存所有相加得到的和,當k足夠小時,空間有一定浪費。所以我的思路是將相加和的前k個數先塞進k大小的陣列並通過快速排序將新陣列調整為有序陣列。然後將後面m*n-k個和依次插入陣列,多出的一位捨棄。插入的方法我使用的是二分法。時間複雜度為o((log2(k))*(m+n)),空間複雜度為o(k)。
程式碼如下:
#include<iostream>
using namespace std;
int a[6] = { 5, 1, 2, 3, 9, 0 };
int b[8] = { 7, 6, 4, 5, 9, 1, 8, 2 };
//將數字分為兩半前面的比關鍵字大後面的比關鍵字小
int Partition(int start, int end, int *arr){
int temp = *(arr + start);
while (start < end)
{
//下面第二個判斷條件一定帶上=否則陣列中有重複元素則死迴圈
while (start < end && *(arr + end) <= temp)
{
end--;
}
*(arr + start) = *(arr + end);
while (start < end && *(arr + start) >= temp)
{
start++;
}
*(arr + end) = *(arr + start);
}
*(arr + start) = temp;
return end;
}
void QuickSort(int start, int end, int * arr) {
if (start < end)
{
int temp = Partition(start, end, arr);
QuickSort(start, temp - 1, arr);
QuickSort(temp + 1, end, arr);
}
}
//這裡使用二分法插入元素,多餘一位捨棄
void InsertNewNum(int * arr, int start, int end, int n, int length){
int temp = (end - start + 1) / 2 + start;
if (*(arr + temp) < n) {
if (temp - 1 < 0 || *(arr + temp - 1) > n) {
for (int i = length - 1; i >= temp + 1; i--) {
*(arr + i) = *(arr + i - 1);
}
*(arr + temp) = n;
return;
}
else
{
InsertNewNum(arr, start, temp - 1, n, length);
}
}
//if (*(arr + temp) > n)
else
{
if (temp + 1 > length - 1 || *(arr + temp + 1) < n) {
for (int i = length - 1; i >= temp + 2; i--) {
*(arr + i) = *(arr + i - 1);
}
*(arr + temp + 1) = n;
return;
}
else
{
InsertNewNum(arr, temp + 1, end, n, length);
}
}
}
void CreateArray(int * arr, int length) {
int m = 0;
int n = 0;
for (int i = 0; i < length; i++) {
if (m >= 6) {
n++;
m = 0;
}
*(arr + i) = a[m++] + b[n];
}
}
int main() {
int k = 0;
std::cin >> k;
if (k > 6 * 8) {
std::cout << "輸入錯誤" << endl;
}
int * result = (int *)malloc(k * sizeof(int));
CreateArray(result, k);
for (int i = 0; i < k; i++) {
std::cout << *(result + i) << " ";
}
cout << endl;
QuickSort(0, k - 1, result);
for (int i = 0; i < k; i++) {
std::cout << *(result + i) << " ";
}
cout << endl;
//將後面6*8-k個和依次插入小根堆中
int m = 6 - 1;
int n = 8 - 1;
for (int i = 0; i < 6 * 8 - k; i++) {
if (m < 0) {
m = 6 - 1;
n--;
}
int temp = a[m--] + b[n];
InsertNewNum(result, 0, k - 1, temp, k);
}
for (int i = 0; i < k; i++) {
std::cout << *(result + i) << endl;
}
while (1) {
}
}