Find Nth element from the two unsorted Array - arrays

Given two unsorted int arrays, find the kth element in the merged, sorted array.
example:
int[] a= [3 1 7]
int[] b = [4 9]
k: 3
return 4 (non-Zero based index)
Please do not provide the straight forward solution where merge two array and sort and find the Nth element. I am looking for more efficient solution i.e using Heap, QuickSort. and make sure arrays are unsorted.
P.S: I know there are many similar questions of above posted in SO but i couldn't find any correct way of implementation in any of them.

As it stands your example is wrong.
Assuming its int[] a= [3 1 7] int[] b = [4 9] k: 3 return 7.
Loop through both arrays and push to a min-heap. After your done, pop k times from the heap and you will have the kth (largest) element from the merged array.
PriorityQueue<Integer> minHeap=new PriorityQueue();
for (Integer i : a)
{
minHeap.add(i);
}
for (Integer i : b)
{
minHeap.add(i);
}
int count=1;// 1 based index
while(!minHeap.isEmpty())
{
Integer head=minHeap.poll();
count++;
if(count==k)
return head;
}
Code above is untested. But it should roughly look like the above.

The general term for this problem is Selection Algorithm, which Wikipedia has a great article on.
Finding the kth element of two unsorted arrays is equivalent to finding the kth element of one--just pretend you've concatenated the two. A simple algorithm from the linked page is Quickselect, which is essentially Quicksort but only recursing into the half that contains the kth element. Essentially,
Use the first element as the pivot
Iterate over the array, assigning items <= to the pivot to one array, and > to another, until an array has grown large enough that it must contain the desired element
Recurse on that array, offsetting k if necessary

C# code using quick select algorithm:
private void MergeUnsortedArray(int[] A1, int[] A2)
{
int[] c = new int[A1.Length + A2.Length];
int length = 0;
for (int i = 0; i < A1.Length; i++)
{
c[i] = A2[i];
length++;
}
for (int j = 0; j < A2.Length; j++)
{
c[length + j + 1] = A2[j];
}
quickselect(c, 0, c.Length, 3);
}
private int quickselect(int[] G, int first, int last, int k)
{
if (first <= last)
{
int pivot = partition(G, first, last);
if (pivot == k)
{
return G[k];
}
if (pivot < k)
{
return quickselect(G, first, pivot - 1, k);
}
return quickselect(G, pivot + 1, last, k);
}
return 0;
}
private int partition(int[] G, int first, int last)
{
int pivot = (first + last) / 2;
swap(G, last, pivot);
for (int i = first; i < last; i++)
{
if (G[i] < G[last])
{
swap(G, i, first);
first++;
}
}
swap(G, first, last);
return first;
}
private void swap(int[] G, int x, int y)
{
int tmp = G[x];
G[x] = G[y];
G[y] = tmp;
}

Related

A question regarding making ordered pairs from every element in an array

I was curious about how I could possibly iterate through an array, and keep track of every single possible ordered pair.
To create a problem to illustrate this; lets say I have a function that takes in an input array, the length of that array and a "target" which is the product of 2 values, and outputs an array consisting of the indices of the input array that you need to multiply in order to get the "target".
int* multipairs(int* inputarray, int arraysize, int target){
/code
}
For example:
Given an array, arr = [2, 5, 1, 9, 1, 0, 10, 2], and target = 50
It should return output = [1,6].
In my mind, I would iterate through the arrays as follow;
(0,1) -> (0,2) -> (0,3) -> (0,4)....
In the second pass I would do:
(1,2) -> (1,3) -> (1,4)...
.
.
.
and so on
I have the idea of what I want to do, but I am unfamiliar with C programming, and have no idea how to make a proper for loop. Please help me figure this out.
Your description of the algorithm is complete - as you say, the first item in the pair is iterating over all the array indices. For each of those, you want to iterate over all the pairs that follow that in the array.
for (int i = 0, i < arraysize; i++)
{
for (int j = i + 1; j < arraysize; j++)
{
// operate on pair array[i] and array[j]
}
}
You can use nested for-loops to solve your problem.
int* multipairs(int* inputarray, int arraysize, int target){
int i, j, k = -1;
/*
Maximum number of such pairs can be arraysize*(arraysize-1)/2
Since, for each pair we store two indices (0-indexed),
maximum size of output array will be arraysize*(arraysize-1)
*/
int maxsize = arraysize*(arraysize-1);
int *output = (int*)malloc(sizeof(int)*maxsize);
for (i = 0, i < arraysize; i++){
for (j = i + 1; j < arraysize; j++){
if(inputarray[i] * inputarray[j] == target){
output[++k] = i;
output[++k] = j;
}
}
}
return output;
}

Different even and odd sorting in Quicksort

I've got such an algorithmic problem: I need to make Quicksort to work like this:
1) Indexes of array which are odd numbers should be sorted from smallest to largest
2) Even indexes should be sorted from largest to smallest.
So if we've got array: 2 5 1 3 4 0 6 2 5,
we should get sth like: 6 0 5 2 4 3 2 5 1
Here is my implementation of quicksort in C:
void quicksort(int tab[], int start, int end) {
int i=start;
int j=end;
int x=tab[(i+j)/2];
do {
while(tab[i]<x) i++;
while(tab[j]>x) j--;
if(i<=j) {
int tmp=tab[i];
tab[i]=tab[j];
tab[j]=tmp;
i++;
j--;
}
} while(i<=j);
if(start<j) quicksort(tab,start,j);
if(i<end) quicksort(tab,i,end);
}
Is it possible to make it using just one quicksort or I should try sth like creating two functions: one will sort odd indexes and second one even indexes?
Is it possible to make it using just one quicksort or I should try sth like creating two functions: one will sort odd indexes and second one even indexes?
quick sort is generally used to sort elements in ascending or descending order so I don't think it'd be useful to just sort the elements in required pattern ( which is neither ascending nor descending and even no particular pattern is guaranteed in the answer array ) using only quick sort.
In my opinion creating an additional custom function say required_sort() and sort elements as required along with the help of qucksort() (here in my case it sorts in ascending order) would be the best way to go
void required_sort(int array[], int size_of_array)
{
int no_of_even_elements, no_of_odd_elements
if(size_of_array%2 == 0)
{
no_of_even_elements = no_of_odd_elements = n/2;
}
else
{
no_of_even_elements = (n/2)+1;
no_of_odd_elements = n/2;
}
int even[no_of_even_elements], odd_even[elements];
//inserting elements into new arrays
for(int index=0; index < size_of_array; index++)
{
if(index%2 == 0)
{
even[index/2] = array[index];
}
else
{
odd[index/2] = array[index];
}
}
//call quicksort function to sort the even[] array in ascending order
//call quicksort function to sort the odd[] array in ascending order
for(int index=0; index < size_of_array; index++)
{
if(index%2 == 0)
{
array[index] = even[(no_of_even_elements)-(index/2)];
}
else
{
array[index] = odd[index/2];
}
}
}
Explanation of required_sort :
first check whether size_of_array is even or odd
if size_of_array is even then there are equal number of elements at odd indices and even indices. so
no_of_even_elements = no_of_odd_elements = n/2
if size_of_array is odd then there are equal number of elements at odd indices and even indices. so
no_of_even_elements = (n/2)+1
no_of_odd_elements = n/2
create two more arrays. say odd[no_of_odd_elements] and even[no_of_even_elements]
in first array store the elements at odd indices and in the second the elements at even indices.
use quicksort() (in ascending order) to sort both the arrays
now using a for loop to update the values of original array[] this way :
for(int index=0; index < size_of_array; index++)
{
if(index%2 == 0)
{
array[index] = even[(no_of_even_elements)-(index/2)];
}
else
{
array[index] = odd[index/2];
}
}
hope this helps :)
You can parameterize your quicksort algorithm in order to support (1) partial sorting based on a step size and (2) the sorting direction.
void quicksort2(int tab[], int start, int end, int step, int (*comparer)(int, int))
introducing a parameter step that is used to access elements that are step elements away from start and end
Whenever an index is changed, use step size instead of 1: i+=step;, j-=step; and so on.
Computing the middle element for pivot becomes slightly more complex in order to support uneven indices with step size > 1: int mid = (end / step - start / step) / 2 * step + start; int x=tab[mid];
The start and end index are required to be a multiple of step apart.
changing the comparison to a comparer function instead of native < and > operator usage
The comparer function is expected to return negative values for a < b and positive values for b < a. Usage: while(comparer(tab[i],x) < 0) // ...
Putting it all together:
void quicksort(int tab[], int start, int end, int step, int (*comparer)(int, int))
{
int i=start;
int j=end;
int mid = (end / step - start / step) / 2 * step + start;
int x=tab[mid];
do {
while(comparer(tab[i],x) < 0) i+=step;
while(comparer(tab[j],x) > 0) j-=step;
if(i<=j) {
int tmp=tab[i];
tab[i]=tab[j];
tab[j]=tmp;
i+=step;
j-=step;
}
} while(i<=j);
if(start<j) quicksort(tab,start,j, step, comparer);
if(i<end) quicksort(tab,i,end, step, comparer);
}
I tried to stick close to your initial native quicksort implementation, so this code should look pretty familiar.
This can be used to execute the desired sorting as follows:
Define comparer functions for ascending and descending sortings.
int smaller(int a, int b)
{
return a - b;
}
int bigger(int a, int b)
{
return b - a;
}
And call quicksort twice for the two sub-sortings
int values[] = { 2, 5, 1, 3, 4, 0, 6, 2, 5 };
quicksort(values, 0, 8, 2, &smaller);
quicksort(values, 1, 7, 2, &bigger);
Be careful to get the start and end indices right or add a sanity check for them inside the quicksort function

Kth Ranked Element Among 2 Unsorted Arrays

Let us suppose we have two arrays A[] and B[]. Each array contains n distinct integers which are not sorted. We need to find kth ranked element in the union of the 2 arrays in the most efficient way possible.
(Please dont post answers about merging the arrays and then sorting them to return kth index in the merged array)
You can use the selection algorithm to find the Kth item, in O(N) time, where N is the sum of the sizes of the arrays. Obviously, you treat the two arrays as a single large array.
Union of arrays can be done in linear time. I am skipping that part.
You can use the partition() algorithm which is used in the quick sort. In quick sort, the function will have to recurse two branches. However here we will just conditionally invoke the recursive call and thus only 1-branched recursion.
Main concept: partition() will place the chosen PIVOT element at its appropriate sorted position. Hence we can use this property to select that half of the array in which we are interested and just recurse on that half. This will prevent us from sorting the entire array.
I have written the below code based on the above concept. Assumption rank = 0 implies the smallest element in the array.
void swap (int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int partition (int a[], int start, int end)
{
/* choose a fixed pivot for now */
int pivot = a[end];
int i = start, j;
for (j = start; j <= end-1; j++) {
if (a[j] < pivot) {
swap (&a[i], &a[j]);
i++;
}
}
/* Now swap the ith element with the pivot */
swap (&a[i], &a[end]);
return i;
}
int find_k_rank (int a[], int start, int end, int k)
{
int x = partition (a, start, end);
if (x == k) {
return a[x];
} else if (k < x) {
return find_k_rank (a, start, x-1, k);
} else {
return find_k_rank (a, x+1, end, k);
}
}
int main()
{
int a[] = {10,2,7,4,8,3,1,5,9,6};
int N = 10;
int rank = 3;
printf ("%d\n", find_k_rank (a, 0, N-1, rank));
}

Rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space

The task is to rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space.
Example:
2 1 3 5 4 0
becomes:
3 1 5 0 4 2
I can think of an O(n²) solution. An O(n) solution was presented here:
Increase every array element arr[i] by (arr[arr[i]] % n)*n.
Divide every element by n.
But this is very limited as it will cause buffer overflow.
Can anyone come up with an improvement upon this?
If the values in the array are all positive (or all negative), one way to avoid overflow could be to run the permutation cycles and use the integer sign to mark visited indexes. (Alternatively, if the array length is smaller than 2^(number of bits for one array element - 1), rather than use the sign, we could shift all the values one bit to the left and use the first bit to mark visited indexes.) This algorithm results in both less iterations and less modifications of the original array values during run-time than the algorithm you are asking to improve.
JSFiddle: http://jsfiddle.net/alhambra1/ar6X6/
JavaScript code:
function rearrange(arr){
var visited = 0,tmp,indexes,zeroTo
function cycle(startIx){
tmp = {start: startIx, value: arr[startIx]}
indexes = {from: arr[startIx], to: startIx}
while (indexes.from != tmp.start){
if (arr[indexes.from] == 0)
zeroTo = indexes.to
if (indexes.to == visited){
visited++
arr[indexes.to] = arr[indexes.from]
} else {
arr[indexes.to] = -arr[indexes.from]
}
indexes.to = indexes.from
if (indexes.from != tmp.start)
indexes.from = arr[indexes.from]
}
if (indexes.to == visited){
visited++
arr[indexes.to] = tmp.value
} else {
arr[indexes.to] = -tmp.value
}
}
while (visited < arr.length - 1){
cycle(visited)
while (arr[visited] < 0 || visited == zeroTo){
arr[visited] = -arr[visited]
visited++
}
}
return arr
}
//Traverse the array till the end.
//For every index increment the element by array[array[index] % n]. To get //the ith element find the modulo with n, i.e array[index]%n.
//Again traverse to end
//Print the ith element after dividing the ith element by n, i.e. array[i]/n
class Rearrange
{
void rearrange(int arr[], int n)
{
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
for (int i = 0; i < n; i++)
arr[i] /= n;
}
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println("");
}
public static void main(String[] args)
{
Rearrange rearrange = new Rearrange();
int arr[] = {6, 4, 9, 2, 5, 7};
int n = arr.length;
System.out.println("Given Array is :");
rearrange.printArr(arr, n);
rearrange.rearrange(arr, n);
System.out.println("Modified Array is :");
rearrange.printArr(arr, n);
}
}

Kth smallest element in sorted matrix

This is an interview question.
Find the Kth smallest element in a matrix with sorted rows and columns.
Is it correct that the Kth smallest element is one of a[i, j] such as i + j = K ?
False.
Consider a simple matrix like this one:
1 3 5
2 4 6
7 8 9
9 is the largest (9th smallest) element. But 9 is at A[3, 3], and 3+3 != 9. (No matter what indexing convention you use, it cannot be true).
You can solve this problem in O(k log n) time by merging the rows incrementally, augmented with a heap to efficiently find the minimum element.
Basically, you put the elements of the first column into a heap and track the row they came from. At each step, you remove the minimum element from the heap and push the next element from the row it came from (if you reach the end of the row, then you don't push anything). Both removing the minimum and adding a new element cost O(log n). At the jth step, you remove the jth smallest element, so after k steps you are done for a total cost of O(k log n) operations (where n is the number of rows in the matrix).
For the matrix above, you initially start with 1,2,7 in the heap. You remove 1 and add 3 (since the first row is 1 3 5) to get 2,3,7. You remove 2 and add 4 to get 3,4,7. Remove 3 and add 5 to get 4,5,7. Remove 4 and add 6 to get 5,6,7. Note that we are removing the elements in the globally sorted order. You can see that continuing this process will yield the kth smallest element after k iterations.
(If the matrix has more rows than columns, then operate on the columns instead to reduce the running time.)
O(k log(k)) solution.
Build a minheap.
Add (0,0) to the heap. While, we haven't found the kth smallest element, remove the top element (x,y) from heap and add next two elements [(x+1,y) and (x,y+1)] if they haven't been visited before.
We are doing O(k) operations on a heap of size O(k) and hence the complexity.
This problem can be solved using binary search and optimised counting in a sorted Matrix. A binary search takes O(log(n)) time and for each search value it takes n iterations on average to find the numbers that are smaller than the searched number. The search space for binary search is limited to the minimum value in the Matrix at mat[0][0] and the maximum value mat[n-1][n-1].
For every number that is chosen from the binary search we need to count the numbers that are smaller than or equal to that particular number. And thus the smallest number can be found.
For better understanding you can refer to this video:
https://www.youtube.com/watch?v=G5wLN4UweAM&t=145s
Start traversing the matrix from the top-left corner (0,0) and use a binary heap for storing the "frontier" - a border between a visited part of the matrix and the rest of it.
Implementation in Java:
private static class Cell implements Comparable<Cell> {
private final int x;
private final int y;
private final int value;
public Cell(int x, int y, int value) {
this.x = x;
this.y = y;
this.value = value;
}
#Override
public int compareTo(Cell that) {
return this.value - that.value;
}
}
private static int findMin(int[][] matrix, int k) {
int min = matrix[0][0];
PriorityQueue<Cell> frontier = new PriorityQueue<>();
frontier.add(new Cell(0, 0, min));
while (k > 1) {
Cell poll = frontier.remove();
if (poll.y + 1 < matrix[poll.x].length) frontier.add(new Cell(poll.x, poll.y + 1, matrix[poll.x][poll.y + 1]));
if (poll.x + 1 < matrix.length) frontier.add(new Cell(poll.x + 1, poll.y, matrix[poll.x + 1][poll.y]));
if (poll.value > min) {
min = poll.value;
k--;
}
}
return min;
}
As people mentioned previously the easiest way is to build a min heap. Here's a Java implementation using PriorityQueue:
private int kthSmallestUsingHeap(int[][] matrix, int k) {
int n = matrix.length;
// This is not necessary since this is the default Int comparator behavior
Comparator<Integer> comparator = new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
// building a minHeap
PriorityQueue<Integer> pq = new PriorityQueue<>(n*n, comparator);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
pq.add(matrix[i][j]);
}
}
int ans = -1;
// remove the min element k times
for (int i = 0; i < k; i++) {
ans = pq.poll();
}
return ans;
}
Kth smallest element in the matrix :
The problem can be narrowed down as below.
if k is 20, then take k*k matrix (where answer will definitely lie.)
Now you can merge the rows in pair repeatedly to build a sorted array and then find the kth smallest number.
//int arr[][] = {{1, 5, 10, 14},
// {2, 7, 12, 16},
// {4, 10, 15, 20},
// {6, 13, 19, 22}
//};
// O(k) Solution
public static int myKthElement(int arr[][], int k) {
int lRow = 1;
int lCol = 0;
int rRow = 0;
int rCol = 1;
int count = 1;
int row = 0;
int col = 0;
if (k == 1) {
return arr[row][col];
}
int n = arr.length;
if (k > n * n) {
return -1;
}
while (count < k) {
count++;
if (arr[lRow][lCol] < arr[rRow][rCol]) {
row = lRow;
col = lCol;
if (lRow < n - 1) {
lRow++;
} else {
if (lCol < n - 1) {
lCol++;
}
if (rRow < n - 1) {
lRow = rRow + 1;
}
}
} else {
row = rRow;
col = rCol;
if (rCol < n - 1) {
rCol++;
} else {
if (rRow < n - 1) {
rRow++;
}
if (lCol < n - 1) {
rCol = lCol + 1;
}
}
}
}
return arr[row][col];
}

Resources