basic thing from a job interview - using linked list,arrays - arrays

I got this question on a job interview, and i could't solve it.
i think i was just really nervous because it doesn't look this hard.
Arr is a given integer array, size n. Sol is a given empty array,
size n.
for each i (i goes from 0 to n-1 ) you have to put in Sol[i] the index
in Arr of the closest elemnt appears on the left side, that is smaller
than Arr[i]. meaning: Sol[i]=max{ j | j < i; Arr[j] < Arr[i] }. if
the is no such index, put -1.
for example: Arr is [5,7,9,2,8,11,16,10,12] Sol is
[-1,0,1,-1,3,4,5,4,7]
time complexity: o(n) space complexity: o(n)
I tried to scan the array from the end to the start, but I didn't know how to continue.
I was asked to use only array and linked list.
I had 10 minutes to solve it, so guess it is not that hard.
thanks a lot!!

Note that for Arr[] with length < 2 there are trivial solutions. This pseudo code assumes that Arr[] has a length >= 2.
int Arr[] = {5,7,9,2,8,11,16,10,12};
int Sol[] = new int[9];
Stack<int> undecided; // or a stack implemented using a linked list
Sol[0] = -1; // this is a given
for(int i = Arr.length() - 1; i != 0; --i) {
undecided.push(i); // we haven't found a smaller value for this Arr[i] item yet
// note that all the items already on the stack (if any)
// are smaller than the value of Arr[i] or they would have
// been popped off in a previous iteration of the loop
// below
while (!undecided.empty() && (Arr[i-1] < Arr[undecided.peek()])) {
// the value for the item on the undecided stack is
// larger than Arr[i-1], so that's the index for
// the item on the undecided stack
Sol[undecided.peek()] = i-1;
undecided.pop();
}
}
// We've filled in Sol[] for all the items have lesser values to
// the left of them. Whatever is still on the undecided stack
// needs to be set to -1 in Sol
while (!undecided.empty()) {
Sol[undecided.peek()] = -1;
undecided.pop();
}
To be honest, I'm not sure I would have come up with this in an interview situation given a 10 minute time limit.
A C++ version of this can be found on ideone.com: https://ideone.com/VXC0yq

int Arr[] = {5,7,9,2,8,11,16,10,12};
int Sol[] = new int[9];
for(int i = 0; i < Arr.length; i++) {
int element = Arr[i];
int tmp = -1;
for(int j = 0 ;j < i; j++) {
int other = Arr[j];
if (other < element) {
tmp = j;
}
}
Sol[i] = tmp;
}

Related

Could you help me with this Array Problem?

An array A with N integers . Each element can be treated as a pointer to others : if A[K] = M then A[K] points to A[K+M].
The array defines a sequence of jumps as follows:
initially, located at element A[0];
on each jump , moves from current element to the destination pointed to by the current ; i.e. if on element A[K] then it jumps to the element pointed to by A[K];
it may jump forever or may jump out of the array.
Write a function: that, given a array A with N integers, returns the number of jumps after which it will be out of the array.
Your approach is right, but instant list reallocation can make program slower.
It is claimed that value range is limited, so you can just put off-range constant (like 2000000) into visited cells as sentinel and stop when you meet such value.
Something like this (not checked):
int sol(int[] A) {
int jump = 0;
int index = 0;
int old = 0;
int alen = A.length;
while (index < alen && index >= 0) {
old = index;
index = A[index] + index;
if (A[index] >= 2000000) {
return -1;
}
A[old] = 2000000;
jump++;
}
return jump;
}

This version of selection sort I tried to make doesnot work properly, but it works surprisingly for larger arrays

I was doing selection sort yesterday. I wondered if I could replace the min and max values to begining and end of the unsorted array every time I iterated. I am just a beginner at programming, so its obvious that this wouldn't work. However, suprisingly, the code below does sort a larger array (~ 30k - 40k) in size. I experimented by generating random values from rand()%2000 and the function sorted the array successfully 28 times in 30 experiments.
But it can't sort something as simple as {4,2,3}
I think there's a bug somewhere, I couldn't figure it out so I've come here.
I'm also curious about the fact that it sorted such large arrays successfully. How?
int *zigzag_sort(int arr[])
{
// loop through array
// find min and max
// replace min at begining and max at end
// keep doing until sorted
int f_idx = 0, l_idx = n-1;
int min_pos, max_pos;
while( f_idx < l_idx ) {
min_pos = f_idx;
max_pos = l_idx;
for(int i = f_idx+1; i <= l_idx; i++)
{
if(arr[i] < arr[min_pos])
min_pos = i;
else if(arr[i] > arr[max_pos])
max_pos = i;
}
swap(&arr[f_idx], &arr[min_pos]);
swap(&arr[l_idx], &arr[max_pos]);
f_idx++;
l_idx--;
}
return arr;
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
Your swaps are not as simple as you think, and there is a hole in your position starting points going in to the inner loop iterations.
First, there are there situations that must be accounted after completing a segment enumeration and finding the segment min-index and max-index locations. They all deal with where you're reading data from, and where you'r'e trying to write it to. There can be partial, or in one case, full, overlap.
After each inner iteration, one of several conditions can transpire...
(min_pos == l_idx) && (max_pos == f_idx) . In other words, the minimum and maximum values are each in the places where the other wants to be. If that is the case ONE swap is needed (each other) and you're done for that iteration.
One of (min_pos == l_idx) or (max_pos == f_idx) is true, but not both. The order of the impending two swaps is important, depending on which of those conditions is true. In short, don't swap something into a slot that is about to be swapped again with the second swap. Ex: If the maximum value resides at the low target position, you need to swap it out to the maximum target position before the minimum value is swapped to the low target position. Otherwise you will dislocate something right after you put it home.
Neither of the above are true, in which case two swaps are still required, but order is irrelevant.
The probability of the special cases in (1) and (2) above increase significantly as you squeeze the iteration window down further and further during the outer loop iteration. For a random ordering, sooner or later it is going to happen.
Secondly, both the min_pos and max_pos starting points should be the same location in the segment, f_idx. It may not seem important, but it is so because the inner loop starts a f_idx+1. that means if the maximum value of the iteration was originally at f_idx you never accounted for it, will not discover it, etc.
The fixed routine is below, with notes where appropriate.
int *zigzag_sort(int arr[], int n)
{
int f_idx = 0, l_idx = n - 1;
while (f_idx < l_idx)
{
// both should start at the same location
int min_pos = f_idx;
int max_pos = f_idx;
for (int i = f_idx + 1; i <= l_idx; i++)
{
if (arr[i] < arr[min_pos])
min_pos = i;
else if (arr[i] > arr[max_pos])
max_pos = i;
}
if (max_pos == f_idx)
{
if (min_pos == l_idx)
{
// swap each other
swap(&arr[max_pos], &arr[min_pos]);
}
else
{ // swap the max out before overwritine with min
swap(&arr[l_idx], &arr[max_pos]);
swap(&arr[f_idx], &arr[min_pos]);
}
}
else
{ // also handle the case of l_idx == min_pos
swap(&arr[f_idx], &arr[min_pos]);
swap(&arr[l_idx], &arr[max_pos]);
}
f_idx++;
l_idx--;
}
return arr;
}
Why doesn't it work for { 4, 2, 3 }?
... // f_idx = 0; l_idx = 2; min_pos = 1; max_pos = 0;
swap(&arr[f_idx], &arr[min_pos]); // swap(&arr[0], &arr[1]) ==> { 2, 4, 3 }
// ===> max_pos is "wrong" now <===
swap(&arr[l_idx], &arr[max_pos]); // swap(&arr[2], &arr[0]) ==> { 3, 4, 2 }

A function that returns 0 or 1 if all elements in the range 0 to n-1 exist in the array, run time O(n)

EDIT:
I forgot to mention that I do not want to allocate another temporarily array.
I am trying to solve a problem in C, which is:
Suppose you were given an array a and it's size N. You know that all of the elements in the array are between 0 to n-1. The function is supposed to return 0 if there is a missing number in the range (0 to n-1). Otherwise, it returns 1. As you can understand, duplicates are possible. The thing is that its supposed to run on O(n) runtime.
I think I managed to do it but i'm not sure. From looking at older posts here, it seems almost impossible and the algorithm seems much more complicated then the algorithm I have. Therefore, something feels wrong to me.
I could not find an input that returns the wrong output yet thou.
In any case, I'd appreciate your feedback- or if you can think of an input that this might not work for. Here's the code:
int missingVal(int* a, int size)
{
int i, zero = 0;
for (i = 0; i < size; i++)
//We multiply the element of corresponding index by -1
a[abs(a[i])] *= -1;
for (i = 0; i < size; i++)
{
//If the element inside the corresponding index is positive it means it never got multiplied by -1
//hence doesn't exist in the array
if (a[i] > 0)
return 0;
//to handle the cases for zeros, we will count them
if (a[i] == 0)
zero++;
}
if (zero != 1)
return 0;
return 1;
}
Just copy the values to another array placing each value in its ordinal position. Then walk the copy to see if anything is missing.
your program works and it is in O(N), but it is quite complicated and worst it modify the initial array
can be just that :
int check(int* a, int size)
{
int * b = calloc(size, sizeof(int));
int i;
for (i = 0; i != size; ++i) {
b[a[i]] = 1;
}
for (i = 0; i != size; ++i) {
if (b[i] == 0) {
free(b);
return 0;
}
}
free(b);
return 1;
}
This problem is the same as finding out if your array has duplicates. Here's why
All the numbers in the array are between 0 and n-1
The array has a size of n
If there's a missing number in that range, that can only mean that another number took its place. Which means that the array must have a duplicate number
An algorithm in O(n) time & O(1) space
Iterate through your array
If the sign of the current number is positive, then make it negative
If you found a negative this means that you have a duplicate. Since all items are originally greater (or equal) than 0
Implementation
int missingVal(int arr[], int size)
{
// Increment all the numbers to avoid an array with only 0s
for (int i = 0; i < size; i++) arr[i]++;
for (int i = 0; i < size; i++)
{
if (arr[abs(arr[i])] >= 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else
return 0;
}
return 1;
}
Edit
As Bruno mentioned if we have an array with all zeros, we could have run into a problem. This is why I included in this edit an incrementation of all the numbers.
While this add another "pass" into the algorithm, the solution is still in O(n) time & O(1) space
Edit #2
Another great suggestion from Bruno which optimizes this, is to look if there's more than one zero instead of incrementing the array.
If there's 2 or more, we can directly return 0 since we have found a duplicate (and by the same token that not all the numbers in the range are in the array)
To overcome the requirement that excludes any extra memory consumption, the posted algorithm changes the values inside the array by simply negating their value, but that would leave index 0 unchanged.
I propose a different mapping: from [0, size) to (-1 - size, -1], so that e.g. {0, 1, 2, 3, 4, ...} becomes {-1, -2, -3, -4, -5, ...}. Note that, for a two's complement representation of integers, INT_MIN = -INT_MAX - 1.
// The following assumes that every value inside the array is in [0, size-1)
int missingVal(int* a, int size) // OT: I find the name misleading
{
int i = 0;
for (; i < size; i++)
{
int *pos = a[i] < 0
? a + (-a[i] - 1) // A value can already have been changed...
: a + a[i];
if ( *pos < 0 ) // but if the pointed one is negative, there's a duplicate
break;
*pos = -1 - *pos;
}
return i == size; // Returns 1 if there are no duplicates
}
If needed, the original values could be restored, before returning, with a simple loop
if ( i != size ) {
for (int j = 0; j < size; ++j) {
if ( a[j] < 0 )
a[j] = -a[j] - 1;
}
} else { // I already know that ALL the values are changed
for (int j = 0; j < size; ++j)
a[j] = -a[j] - 1;
}

How to find the number of elements in the array that are bigger than all elements after it?

I have a function that takes a one-dimensional array of N positive integers and returns the number of elements that are larger than all the next. The problem is exist a function to do it that in a better time? My code is the following:
int count(int *p, int n) {
int i, j;
int countNo = 0;
int flag = 0;
for(i = 0; i < n; i++) {
flag = 1;
for(j = i + 1; j < n; j++) {
if(p[i] <= p[j]) {
flag = 0;
break;
}
}
if(flag) {
countNo++;
}
}
return countNo;
}
My solution is O(n^2). Can it be done better?
You can solve this problem in linear time(O(n) time). Note that the last number in the array will always be a valid number that fits the problem definition. So the function will always output a value that will be greater than equal to 1.
For any other number in the array to be a valid number it must be greater than or equal to the greatest number that is after that number in the array.
So iterate over the array from right to left keeping track of the greatest number found till now and increment the counter if current number is greater than or equal to the greatest found till now.
Working code
int count2(int *p, int n) {
int max = -1000; //this variable represents negative infinity.
int cnt = 0;
int i;
for(i = n-1; i >=0; i--) {
if(p[i] >= max){
cnt++;
}
if(p[i] > max){
max = p[i];
}
}
return cnt;
}
Time complexity : O(n)
Space complexity : O(1)
It can be done in O(n).
int count(int *p, int n) {
int i, currentMax;
int countNo = 0;
currentMax = p[n-1];
for(i = n-1; i >= 0; i--) {
if(currentMax < p[i])
{
countNo ++;
currentMax = p[i];
}
}
return countNo;
}
Create an auxillary array aux:
aux[i] = max{arr[i+1], ... ,arr[n-1] }
It can be done in linear time by scanning the array from right to left.
Now, you only need the number of elements such that arr[i] > aux[i]
This is done in O(n).
Walk backwards trough the array, and keep track of the current maximum. Whenever you find a new maximum, that element is larger than the elements following.
Yes, it can be done in O(N) time. I'll give you an approach on how to go about it. If I understand your question correctly, you want the number of elements that are larger than all the elements that come next in the array provided the order is maintained.
So:
Let len = length of array x
{...,x[i],x[i+1]...x[len-1]}
We want the count of all elements x[i] such that x[i]> x[i+1]
and so on till x[len-1]
Start traversing the array from the end i.e. at i = len -1 and keep track of the largest element that you've encountered.
It could be something like this:
max = x[len-1] //A sentinel max
//Start a loop from i = len-1 to i = 0;
if(x[i] > max)
max = x[i] //Update max as you encounter elements
//Now consider a situation when we are in the middle of the array at some i = j
{...,x[j],....x[len-1]}
//Right now we have a value of max which is the largest of elements from i=j+1 to len-1
So when you encounter an x[j] that is larger than max, you've essentially found an element that's larger than all the elements next. You could just have a counter and increment it when that happens.
Pseudocode to show the flow of algorithm:
counter = 0
i = length of array x - 1
max = x[i]
i = i-1
while(i>=0){
if(x[i] > max){
max = x[i] //update max
counter++ //update counter
}
i--
}
So ultimately counter will have the number of elements you require.
Hope I was able to explain you how to go about this. Coding this should be a fun exercise as a starting point.

Iterate ALL the elements of a circular 2D array exactly once given a random starting element

We are given a 2-dimensional array A[n,m] with n rows and m columns and an element of that array chosen at random R.
Think of the array as being circular in that when we visit A[n-1, m-1] the next element we visit would be A[0, 0].
Starting with element R, we want to visit each element exactly once and call function foo() before moving to the next element.
The following is my first implementation but there is a bug. The bug being that if we start at row x somewhere between 0 and n-1, we will not visit element from 0 to x-1 in that column.
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
// Look at each column once
for (int i = 0; i < m; ++i)
{
for (; curr_row < n; ++curr_row)
{
foo(A[curr_row][curr_col]);
}
curr_row = 0;
curr_col = (curr_col + 1) % m;
}
What is a clean way to do this traversal such that we meet the above requirements?
Just move to the next index, and check whether you are back at the start, in which case, stop:
// should be something that guarantees in-range indices
curr_row = rand();
curr_col = rand();
int i = curr_row, j = curr_col;
do {
foo(A[i][j]);
++j;
if (j == n) {
j = 0;
++i;
if (i == m) {
i = 0;
}
}
}while(i != curr_row || j != curr_col);
This doesn't do what your implementation does, but what the question title asks for.
quite rusty with c , but it should be the same:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
//first row
for(int j=curr_col;j<m;++j)
foo(A[curr_row][j]);
//rest of the rows
for(int i=(curr_row+1)%n;i!=curr_row;i=(i+1)%n)
for(int j=0;j<m;++j)
foo(A[i][j]);
//first row , going over missed cells
for(int j=0;j<curr_col;++j)
foo(A[curr_row][j]);
if you care a lot about performance , you can also divide the second loop so that there won't be a "%" at all .
another alternative , since C has 2d arrays in a simple array:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
int start=curr_row*m+curr_col;
int maxCell=n*m;
int end=(start-1)%maxCell;
for(int i=start;i!=end;i=(i+1)%maxCell)
foo(A[i]);
foo(A[end]);
could have a tiny math bug here and there ,but the idea is ok.
A[curr_row, curr_col] is not the syntax used to access a member of a multidimensional array; instead, you want A[curr_row][curr_col], assuming the array was declared correctly. A[curr_row, curr_col] will invoke the comma operator, which effectively computes the first value, then throws it away and calculates the second value, then indexes the array with that value.

Resources