Give you two sorted array, find the k-th smallest elements of union of A and B, you can assume that there are no duplicate elements. the size of A is m, and size of B is n, both them are in acsending order.
At first, we can use brute-force, malloc a new array of size m+n, and merge A and B into this new array, then we can get the k-th smallest element, or k-th smallest elements. time complexity is O(m+n), and the space complexity is O(m+n);
A better way, using two pointers: i, and j, i proints head of A, j points to head of B, at the same time make a new malloc of array of size k. then we compare A[i] and B[j], we get the minimum of them and increase pointer of the minimum one in order to get next index of the array its belonged to. time complexity is O(k), and space complexity is O(k). here is the codes:
#include
#include
using namespace std;
int *get_k_th_minimum(int *a, int len_a, int *b, int len_b, int k) {
int p = 0;
int i = 0;
int j = 0;
int *c = (int*)malloc(sizeof(int) * k);
if(a == NULL || b == NULL || k > (len_a + len_b)) {
return NULL;
}
while(p < k && i < len_a && j < len_b) {
if(a[i] < b[j]) {
c[p++] = a[i];
i++;
} else {
c[p++] = b[j];
j++;
}
}
return c;
}
void main() {
int a[] = {1, 3, 5, 7, 9};
int b[] = {2, 4, 6, 8, 10};
int len_a = sizeof(a) / sizeof(int);
int len_b = sizeof(b) / sizeof(int);
int k = 5;
int *p = get_k_th_minimum(a, len_a, b, len_b, k);
int i = 0;
if(p) {
for(i = 0; i < k; i++) {
cout << p[i] << " ";
}
cout << endl;
}
getchar();
}
Another side note is regarding the choices of i and j. The below code would subdivide both arrays using its array sizes as weights. The reason is it might be able to guess the k-th element quicker (as long as the A and B is not differed in an extreme way; ie, all elements in A are smaller than B). If you are wondering, yes, you could choosei to be A’s middle. In theory, you could choose any values for i and j as long as the invariant i+j = k-1 is satisfied.
here is the code:
#include
#include
using namespace std;
int flag = 0;
int get_k_th_minimum(int *a, int m, int *b, int n, int k) {
assert(m >= 0);
assert(n >= 0);
assert(k <= (m + n));
int i = (int)((double)m / (m + n) * (k + 1));
int j = (k - 1) - i;
assert(i >= 0);
assert(j >= 0);
assert(i <= m);
assert(j <= n);
int Ai_1 = ((i == 0) ? INT_MIN : a[i-1]);
int Bj_1 = ((j == 0) ? INT_MIN : b[j-1]);
int Ai = ((i == m) ? INT_MAX : a[i]);
int Bj = ((j == n) ? INT_MAX : b[j]);
if(Bj_1 < Ai && Ai < Bj) {
flag = 0;
return Ai;
} else if(Ai_1 < Bj && Bj < Ai) {
flag = 1;
return Bj;
}
assert((Ai > Bj && Ai_1 > Bj) || (Ai < Bj && Ai < Bj_1));
if(Ai < Bj) {
get_k_th_minimum(a + i + 1, m - i - 1, b, j, k - i - 1);
} else {
get_k_th_minimum(a, i, b + j + 1, n - j - 1, k - j - 1);
}
}
void main() {
int i = 0;
int j = 0;
int a[] = {1, 3, 5, 7, 9};
int b[] = {2, 4, 6, 8, 10};
int len_a = sizeof(a) / sizeof(int);
int len_b = sizeof(b) / sizeof(int);
int k = 6;
int result = get_k_th_minimum(a, len_a - 1, b, len_b - 1, k);
if(flag == 0) {
while(a[i] != result) {
cout << a[i] << " ";
i++;
}
for(j = 0; j < k - i - 1; j++) {
cout << b[j] << " ";
}
cout << result << endl;
} else {
while(b[i] != result) {
cout << b[i] << " ";
i++;
}
for(j = 0; j < k - i - 1; j++) {
cout << a[j] << " ";
}
cout << result << endl;
}
getchar();
}