I tried to solve one programming problem(neither my homework nor any of my interview/test, but can be a good candidate) online.
The problem is given below. My code below functionally is correct, but it is of run-time complexity O(N2), where as solution expected should be in O(N).
I tried couple of other approaches to get it optimize – 1)Sorted the array and then tried if I could get this working, but since sorting causes indexes of the original numbers to be lost, i even kept those in a separate array, and did sovle it but even that ended up being O(N2). I am sure sorting of the array would help here to get to O(N) but just not been able to nail it.
Any help in getting this problem done in O(N) using any approach would be useful.
(Apologies for long post)
Consider a zero-indexed array A of N integers. Indices of this array are integers from 0 to N−1. Take an index K. Index J is called an ascender of K if A[J] > A[K]. Note that if A[K] is a maximal value in the array A, then K has no ascenders.
Ascender J of K is called the closest ascender of K if abs(K−J) is the smallest possible value (that is, if the distance between J and K is minimal). Note that K can have at most two closest ascenders: one smaller and one larger than K.
For example, let us consider the following array A:
A[0] = 4 A[1] = 3 A[2] = 1 A[3] = 4 A[4] = -1 A[5] = 2 A[6] = 1 A[7] = 5 A[8] = 7
If K = 3 then K has two ascenders: 7 and 8. Its closest ascender is 7 and distance between K and 7 equals abs(K−7) = 4.
Write a function:
struct Results {
int * R;
int N;
};
struct Results array_closest_ascenders(int A[], int N);
that, given a zero-indexed array A of N integers, returns a zero-indexed array R of N integers, such that (for K = 0,…, N−1):
if K has the closest ascender J, then R[K] = abs(K−J); that is, R[K] is equal to the distance between J and K,
if K has no ascenders then R[K] = 0.
For example, given the following array A:
A[0] = 4 A[1] = 3 A[2] = 1 A[3] = 4 A[4] = -1 A[5] = 2 A[6] = 1 A[7] = 5 A[8] = 7
the function should return the following array R:
R[0] = 7 R[1] = 1 R[2] = 1 R[3] = 4 R[4] = 1 R[5] = 2 R[6] = 1 R[7] = 1 R[8] = 0
Array R should be returned as:
a structure Results (in C), or
a vector of integers (in C++), or
a record Results (in Pascal), or
an array of integers (in any other programming language).
Assume that:
N is an integer within the range [0..50,000];
each element of array A is an integer within the range [−1,000,000,000..1,000,000,000].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
My solution (O(N2)):
#include <math.h>
#include "stdio.h"
#include "stdlib.h"
struct Results
{
int *R;
int N;
};
struct Results array_closest_ascenders ( int A[], int N )
{
struct Results result;
int i,j,asc_found=0;
result.R = (int*)malloc(sizeof(int)*N);
for(i=0;i<N;i++)
result.R[i] = N;
result.N = N;
for(i=0;i<N;i++)
{
asc_found = 0;
for(j=0;j<N;j++)
{
if(A[i] < A[j])
{
//if(result.R[i] == 0)
{
if(result.R[i] > abs(i-j))
{
result.R[i] = abs(i-j);
asc_found = 1;
}
}
}
}
if(asc_found == 0)
result.R[i] = 0;
}
return result;
}
void main()
{
//int A[] = {4, 3, 1, 4, -1, 2, 1, 5, 7};
int A[] = {691446939, -241956306, 485954938, 604054438, 383714185, -656099986, -357341170, -255988102, -139683363, -463281394, -382925609, 712727854};
struct Results tmp;
tmp = array_closest_ascenders(A,sizeof(A)/sizeof(A[0]));
}
Left closest ascender and right closest ascender can be considered separately. We go through the array once, computing left closest ascenders; and once again in the opposite direction, computing right closest ascenders. The closest ascender is the closer of the two.
In the algo below only left ascenders are considered. A stack of indices keeps track of left ascenders (all of them) of the current element. The closest ascender is always at the top of the stack.