1. 程式人生 > >演算法之求兩個陣列各任意一位相加和組成的新陣列中的前k位

演算法之求兩個陣列各任意一位相加和組成的新陣列中的前k位

輸入時兩個整數陣列,他們任意兩個數的和又可以組成一個數組,求這個和中前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) {
	
	}
}