I was asked the following question during the interview (Unfortunately I couldn't find the answer better than N^2)
For a given array arr for unsigned int of size N,for each element (in the index i) I should return an element in the index j (j > i),such that arr[j] > arr[i]
I.e. I should return array res in which res[i] has a arr[j],j>i,arr[j] > arr[i],j is min among all indices k ,such that arr[k] > arr[i]
for example
arr[] = {3,1,4,2,5,7};
res[] = {2,2,4,4,5,-1};//-1 says no such index
Any proposition to do it in better time complexity?
Thanks
O(N) Time and O(N) Space Complexity:
Create empty stack, iterate the array from the right
for each iterated item:
keep popping from the stack as long as item on the top is smaller than current, then if the stack becomes empty there's no bigger element on the right, if not that's your first bigger item on the right for current element, push current item on the stack
void GetFirstRight(int* arr, int size, int* res){
stack<int> s;
for (int i = size - 1; i >= 0; --i) {
while (!s.empty() && s.top() <= arr[i]) s.pop();
if (s.empty()) {
res[i] = -1;
} else {
res[i] = s.top();
}
s.push(arr[i]);
}
}
O(n) algorithm:
Maintain a stack of indexes that are still not solved. This will be sorted so that the minimum still unsolved value is on the top. As you reach a new element pop from the stack until the value of the new element is less than the value on top of the stack. For each that you pop, the answer is the current index. Then push on the current index. At the end, the result for anything still on the stack is -1.
Code (C++):
stack<int> unsolved;
int arr[] = {3,1,4,2,5,7}, N = 6;
int res[1234];
int main() {
for (int i = 0; i < N; i++) {
while (!unsolved.empty() && arr[unsolved.top()] < arr[i]) {
res[unsolved.top()] = i;
unsolved.pop();
}
unsolved.push(i);
}
while (!unsolved.empty()) {
res[unsolved.top()] = -1;
unsolved.pop();
}
// Print results
for (int i = 0; i < N; i++) printf("%d%c", res[i], i==N-1 ? '\n' : ' ');
return 0;
}
Output:
2 2 4 4 5 -1
Keep a parallel array b. make b[0]=0.
Make a run to iterate thru the elements of a. as you go along, set the values of b to the differences of consecutive cells of a.
so, if
a[0]=9
a[1]=4
a[2]=17
a[3]=2
a[4]=3
a[5]=6
a[6]=0
a[7]=3
a[8]=1
a[9]=1
a[10]=7
then,
b[0]=0
b[1]=-5
b[2]=13
b[3]=-15
b[4]=1
b[5]=3
b[6]=-6
b[7]=3
b[8]=-2
b[9]=0
b[10]=6
All you should be concerned about is the (-) cells in the b array.
Now, start iterating backwards on array b-- starting from
b[10] in the above eg.
Keep a currentMax value. initially set to the first max (+)
on the array-- nothing you can do about the (-) entries at the end of the array.
As you iterate backwards from b[b.length] down to b[0], do the following:
update currentMax:
currentMax += <value at the current cell of **b**>
if (currentMax<0) then /* you've hit elements-with-no-indexes*/ then keep going till you find a positive b[i] entry, and when you find one, set the value of currentMax to it.
(+) values of currentMax indicate cells that the cell that reset currentMax is the index for all cells visited-so-far, (-) values are no-index cells.
In the above eg, 7 at a[10] is the index of all in a[3]..a[9], because
-currentMax is the one initialized at cell 10 (and not reset afterwards)
-the value of currentMax after all those additions is still (+) all the way up to cell 4 (cell 4 reflects the change from cell 3-to-4)
At b[3], currentMax falls below 0--meaning no index for cell 2.
The value found at b[2] is positive while currentMax is negative-- so make at b[3], currentMax=13 and iterate on.
Linear in the array size-- takes O(n) time.
Related
I've tried shifting elements backwards but it is not making the array completely empty.
for(i=pos;i<N-count;i++)
{
A[i]=A[i+1];
}
Actually, I've to test for a key value in an input array and if the key value is present in the array then I've to remove it from the array. The loop should be terminated when the array becomes empty. Here "count" represents the number of times before a key value was found and was removed. And, "pos" represents the position of the element to be removed. I think dynamic memory allocation may help but I've not learned it yet.
From your description and code, by "delete" you probably mean shift the values to remove the given element and shorten the list by reducing the total count.
In your example, pos and count would be/should be the similar (off by 1?) .
The limit for your for loop isn't N - count. It is N - 1
So, you want:
for (i = pos; i < (N - 1); i++) {
A[i] = A[i + 1];
}
N -= 1;
To do a general delete, given some criteria (a function/macro that matches on element(s) to delete, such as match_for_delete below), you can do the match and delete in a single pass on the array:
int isrc = 0;
int idst = 0;
for (; isrc < N; ++isrc) {
if (match_for_delete(A,isrc,...))
continue;
if (isrc > idst)
A[idst] = A[isrc];
++idst;
}
N = idst;
int main() {
int arr[] = { 64, 25, 12, 22, 11 };
int n = sizeof(arr) / sizeof(arr[0]);
selectionSort(arr, n);
return 0;
}
void selectionSort(int arr[], int n) {
int i, j, min_idx;
// One by one move boundary of unsorted subarray
for (i = 0; i < n - 1; i++) {
// Find the minimum element in unsorted array
min_idx = i;
for (j = i + 1; j < n; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
// Swap the found minimum element with the first element
swap(&arr[min_idx], &arr[i]);
}
}
I have see this C language code that'll do sorting algorithms called Selection Sort. But my question is in the selectionSort function.
Why in the first for loop, is the condition i < n - 1 whereas in the second loop it is j < n?
What will i < n - 1 do exactly? and why different cases for the second loop? Can you please explain this code to me like I'm in sixth grade of elementary school. Thank You.
The first loop has to iterate up to index n-2 (thus i < n-1) because the second for loop has to check numbers i+1 up to n-1 (thus j < n). If i could get the value n - 1, then the access in if (arr[j] < arr[min_idx]) would be out of bounds, specifically arr[j] would be out of bounds for j==n.
You could think that this implementation of selection sort moves from left to right on the array, leaving always a sorted array on its left. That's why the second for loop starts visiting elements from index i+1.
You could find many resources online to visualize how selection sort works, e.g., Selection sort in Wikipedia
The implementation on Wikipedia is annotated and explains it.
/* advance the position through the entire array */
/* (could do i < aLength-1 because single element is also min element) */
for (i = 0; i < aLength-1; i++)
Selection sort works by finding the smallest element and swapping it in place. When there's only one unsorted element left it is the smallest unsorted element and it is at the end of the sorted array.
For example, let's say we have {3, 5, 1}.
i = 0 {3, 5, 1} // swap 3 and 1
^
i = 1 {1, 5, 3} // swap 5 and 3
^
i = 2 {1, 3, 5} // swap 5 and... 5?
^
For three elements we only need two swaps. For n elements we only need n-1 swaps.
It's an optimization which might improve performance a bit on very small arrays, but otherwise inconsequential in an O(n^2) algorithm like selection sort.
Why in the first for loop, the condition is i < n-1? But in the second loop is j < n?
The loop condition for the inner loop is j < n because the index of the last element to be sorted is n - 1, so that when j >= n we know that it is past the end of the data.
The loop condition for the outer loop could have been i < n, but observe that no useful work would then be done on the iteration when i took the value n - 1. The initial value of j in the inner loop is i + 1, which in that case would be n. Thus no iterations of the inner loop would be performed.
But no useful work is not the same as no work at all. On every outer-loop iteration in which i took the value n - 1, some bookkeeping would be performed, and arr[i] would be swapped with itself. Stopping the outer loop one iteration sooner avoids that guaranteed-useless extra work.
All of this is directly related to the fact that no work needs to be expended to sort a one-element array.
Here is the logic of these nested loops:
for each position i in the array
find the smallest element of the slice starting at this position extending to the end of the array
swap the smallest element and the element at position i
The smallest element of the 1 element slice at the end of the array is obviously already in place, so there is no need to run the last iteration of the outer loop. That's the reason for the outer loop to have a test i < n - 1.
Note however that there is a nasty pitfall in this test: if instead of int we use size_t for the type of the index and count of elements in the array, which is more correct as arrays can have more elements nowadays than the range of type int, i < n - 1 would be true for i = 0 and n = 0 because n - 1 is not negative but the largest size_t value which is huge. In other words, the code would crash on an empty array.
It would be safer to write:
for (i = 0; i + 1 < n; i++) { ...
Assume an array and we start from element at index 0. We want to go from 0 index to last index of the array by taking steps of at max length K.
For example, suppose an array is [10,2,-10,5,20] and K is 2, which means maximum step length is 2 (We can assume K is always possible and less than length of array).
Now as we start from index 0, our score currently is 10 and then we can either go to 2 or can go to -10. Suppose we go to 2 from here so total score becomes 10+2=12. Now from 2 we can go to -10 or 5 so you go to 5 making score 12+5=17. From here you directly go to last index as you have no way other than that, hence total score is 17+20=37.
For given array of length N and an integer K we need to find maximum score we can get.
I thought of a solution, to divide it into sub problems by deciding weather to go at index i or not and recursively call the remaining array. But I sense some dynamic programming out of this problem.
How can this be solved for given array of size N and integer K.
Constraint : 1<=N<=100000 and 1<=K<=N
Came up with a O(n*k) solution.
Main function call would be findMax(A,N,K,0).
MAX = new Array();
MAX[i] = null. For 0<=i<N
null denoting the particular element has not been filled.
procedure findMax(A,N,K,i)
{
if (MAX[i]!=null)
return MAX[i];
else if (i==N-1)
MAX[i]=A[i];
else
{
MAX[i]=A[i]+findMax(A,N,K,i+1);
for (j=2; j<=K&&(i+j)<N; ++j)
if (A[i]+findMax(A,N,K,i+j)>MAX[i])
MAX[i]=A[i]+findMax(A,N,K,i+j);
}
return MAX[i];
}
The problem has optimal sub-structure property. To calculate optimal solution, all sub-problems need to be computed. So at a quick glance, I guess the time complexity wont go below O(n*k).
This can be solved in O(n) time and memory
basically: go from back from i = n-1 to 0 and you have to know somehow what is the best index from i+1 up to i+k right? Then best answer for i would be to jump on the best index in range [i+1, i+k]
To get that information you can create some sort of queue (but you need to be able to perform pop from both sides in c++ you can use dequeue).
In that queue you keep two informations: (time, value), where time is the time at which you pushed element and value is best sum you can get if you start from element.
Now when you are in index i: first pop until current time (lest name it t) minus queue.top.time is > k: while( t-que.top.time > k) que.pop
Then you can take que.top.value + array[i] and that is the best value you can get from index i.
Last part to do is updating queue. You create new element e = (t, que.top.value + array[i]) and take que.back (instead of que.top) and perform
while (que.back.value <= e.value) que.pop_back
Then you can push back
que.push_back(e)
and increase t++
This works because, when your new element has better value then elements inserted on the que in the past its better to keep this element instead, because you will be able to use it longer.
Hope it makes sense :)
Try to walk backward this way you can achieve that in O(n*logk).
If the array was on size 1 the the max was that element. Consider you in the i-element - you can take him or one of the next K element -> choose the one that maximize your final result.
Consider the following pseudo code:
Base on #RandomPerfectHashFunction answer with some change
Consider Max as our answer array and tree as AVL Tree( self balancing binary search Tree)
findMaxStartingFromIndex(A,N,K,i, Max, Tree)
if Max[i] != null
return Max[i]
max = Tree.Max // log k - just go down all the way to the right
if (i + k > N) // less then k element to end of array
max = max(max,0) // take the maximum only if he positive
Max[i] = A[i] + max
Tree.add(Max[i])
if (i + k < N)
Tree.remove(Max[i+k]) // remove the element from tree because it is out of the rolling-window of k elements
return Max[i]
In Main:
Init Max array at size N
Init Tree as empty AVL tree
Max[N-1] = A[N-1]
Tree.add(MAX[N-1])
for (i = N-2; i >= 0 ; i--)
findMaxStartingFromIndex(A,N,K,i, Nax, Tree)
When all done look for the max in the first k element of the Max array (no always choosing the first element is the best option)
Adding finding and removing element to binary search tree is log n -> in our case tree will hold only k element -> we achieve O(n*logk) complexity
This can be done in O(n). I'm assuming you're already familiar with the basic DP algorithm, which runs in O(nk). We have dp[i] = value[i] + (max(dp[j]) for i - k < j < i). The k factor in the complexity comes from finding the minimum of the last k values in our DP array, which we can optimize to O(1).
One optimization might be to maintain a binary search tree containing the last k values, which would make an O(n log k) solution. But we can do better by using a double-ended queue instead of a binary search tree.
We maintain a deque containing the candidates for the maximum of the last k elements. Before we push the current dp value into the back of the deque, we pop off the value at the back if it is less than or equal to the current value. Because the current value is both better (or at least as good) than the value in the back and will be in the deque for longer, the value at the back will never be the maximum in the deque and can be discarded. We repeat this until the value at the back is no longer less than or equal to the current value.
We can then pop off the front value if its index is less than the current index minus k.
The way we popped off numbers from the back makes our queue always decreasing, so the maximum value is at the front.
Note that even though the loop popping off the values at the back might run as much as n - 1 times in an iteration of the main loop, the total complexity is still O(n) because each element in the DP array popped off at most once.
this can be solved with dynamic programming. dp[i] means the maximum scores we can collect from nums[0] to nums[i]. Transition is dp[i] = max(dp[i-1], dp[i-2],...,dp[i-k])+nums[i]. Time complexity is O(nk).
A greedy solution. You might find it is easier to understand.
class Solution {
public static void main(String[] args) {
//Init
int[]path= {10,2,-10,5,20};
int maxStep=2;
int max=path[0];
if(path.length==0)System.out.println(0);
for(int i=0;i<path.length-1;) {
int index=0,temp=Integer.MIN_VALUE;
//for each step, choose the step that has max value
for(int j=1;(j<=maxStep)&&(i+j<=path.length-1);j++) {
if(i+j>path.length-1)break;
if(path[i+j]>temp) {
temp=path[i+j];
index=j;
}
}
//change the index and the max value
i+=index;max+=temp;
}
System.out.println(max);
}
}
This was asked today in my interview .Two of the answers here posted best approach. Just adding code here for the same.
Time Complexity : O(n) n - number of elements of array
package main.java;
import java.util.*;
public class Main {
public static int solve(int[] a, int k) {
int ans = Integer.MIN_VALUE;
MaxSlidingWindow maxSlidingWindow = new MaxSlidingWindow(k);
for (int i = 0; i < a.length; i++) {
ans = maxSlidingWindow.getMax() + a[i];
maxSlidingWindow.add(i, ans);
}
return ans;
}
public static void main(String[] args) {
int[] input = {-9, -11, -10, 5, 20};
System.out.print(Main.solve(input, 2));
}
}
// at any point MaxSlidingWindow will have atmost k nodes
// with 'index' and 'val' monotonically decreasing from head to tail
class MaxSlidingWindow {
int k;
Deque<Node> q;
class Node {
int index;
int val;
Node(int index, int val) {
this.index = index;
this.val = val;
}
}
MaxSlidingWindow(int k) {
this.k = k;
this.q = new LinkedList<Node>();
}
public void add(int index, int val) {
if (q.isEmpty()) {
q.addLast(new Node(index, val));
} else {
if (index - q.peekFirst().index + 1 > k) {
q.pollFirst(); // removing head as it is out of range
}
while (!q.isEmpty() && q.peekLast().val <= val) {
q.pollLast(); // removing values in last less than current
}
q.addLast(new Node(index, val));
}
}
public int getMax() {
if (q.isEmpty()) {
return 0;
}
return q.peekFirst().val;
}
}
Taken from the google interview question here
Suppose that you have a sorted array of integers (positive or negative). You want to apply a function of the form f(x) = a * x^2 + b * x + c to each element x of the array such that the resulting array is still sorted. Implement this in Java or C++. The input are the initial sorted array and the function parameters (a, b and c).
Do you think we can do it in-place with less than O(n log(n)) time where n is the array size (e.g. apply a function to each element of an array, after that sort the array)?
I think this can be done in linear time. Because the function is quadratic it will form a parabola, ie the values decrease (assuming a positive value for 'a') down to some minimum point and then after that will increase. So the algorithm should iterate over the sorted values until we reach/pass the minimum point of the function (which can be determined by a simple differentiation) and then for each value after the minimum it should just walk backward through the earlier values looking for the correct place to insert that value. Using a linked list would allow items to be moved around in-place.
The quadratic transform can cause part of the values to "fold" over the others. You will have to reverse their order, which can easily be done in-place, but then you will need to merge the two sequences.
In-place merge in linear time is possible, but this is a difficult process, normally out of the scope of an interview question (unless for a Teacher's position in Algorithmics).
Have a look at this solution: http://www.akira.ruc.dk/~keld/teaching/algoritmedesign_f04/Artikler/04/Huang88.pdf
I guess that the main idea is to reserve a part of the array where you allow swaps that scramble the data it contains. You use it to perform partial merges on the rest of the array and in the end you sort back the data. (The merging buffer must be small enough that it doesn't take more than O(N) to sort it.)
If a is > 0, then a minimum occurs at x = -b/(2a), and values will be copied to the output array in forward order from [0] to [n-1]. If a < 0, then a maximum occurs at x = -b/(2a) and values will be copied to the output array in reverse order from [n-1] to [0]. (If a == 0, then if b > 0, do a forward copy, if b < 0, do a reverse copy, If a == b == 0, nothing needs to be done). I think the sorted array can be binary searched for the closest value to -b/(2a) in O(log2(n)) (otherwise it's O(n)). Then this value is copied to the output array and the values before (decrementing index or pointer) and after (incrementing index or pointer) are merged into the output array, taking O(n) time.
static void sortArray(int arr[], int n, int A, int B, int C)
{
// Apply equation on all elements
for (int i = 0; i < n; i++)
arr[i] = A*arr[i]*arr[i] + B*arr[i] + C;
// Find maximum element in resultant array
int index=-1;
int maximum = -999999;
for (int i = 0; i< n; i++)
{
if (maximum < arr[i])
{
index = i;
maximum = arr[i];
}
}
// Use maximum element as a break point
// and merge both subarrays usin simple
// merge function of merge sort
int i = 0, j = n-1;
int[] new_arr = new int[n];
int k = 0;
while (i < index && j > index)
{
if (arr[i] < arr[j])
new_arr[k++] = arr[i++];
else
new_arr[k++] = arr[j--];
}
// Merge remaining elements
while (i < index)
new_arr[k++] = arr[i++];
while (j > index)
new_arr[k++] = arr[j--];
new_arr[n-1] = maximum;
// Modify original array
for (int p = 0; p < n ; p++)
arr[p] = new_arr[p];
}
I'm trying to sort an array using Insertion Sort.
Instead of changing and rearranging elements of array itself, I'm using another array named rank to Map to point to original array.
here is my code
int i,j;
int ar[] = {50,14,51,25,10};
int rank[] = {0,1,2,3,4};
for(i=1 ; i< 5 ; ++i) // second element onwards
{
int temp = rank[i]; // stores current value in temp variable
/**
* temp = 1
* j = 0
*/
j = rank[i] - 1;
while ( ar[temp] < ar[ rank[j] ] && j > -1)
{
rank[j+1] = rank[j]; // move elemnts in map forward
j--;
} // end loop
// insert temp at proper place
rank[j+1] = temp;
}
for(i=0 ; i< 5 ; ++i)
printf("Rank : %d, Number : %d \n",rank[i],ar[i]);
But, it's not giving an expected output. Can anyone point towards what is the mistake in the logic ?
You logic flaw is as following:
At this code section
while ( ar[temp] < ar[ rank[j] ] && j > -1)
{
rank[j+1] = rank[j]; // move elemnts in map forward
j--;
} // end loop
rank[j] means the rank of the value at ar[j].
And when you use ar[rank[j]], you are comparing ar[temp] to the value indexed at "the rank of the value at ar[ j ]", which means you are not comparing to the biggest value in the sorted portion of rank[].
Therefore, you may not get into this loop even if ar[temp] is the second smallest
For example:
So far during loop#2 (i = 2)
ar[] : {50,14,51,25,10};
rank[] : {1,0,2,3,4}; ({1,0} is the sorted portion of rank[])
The 0 only means 14 is the smallest value in {50,14} (the scanned portion of ar[])
AND ar[rank[2]] ( ar[0]) only happens to be the largest value in {50,14} (the scanned portion of ar[]) by coincidence
If this value (ar[rank[2]]) is not the largest, and happens to be smaller than ar[temp], you program will just skip the loop. Even if ar[temp] is smaller than all the other values in ar[]
rank[j+1] = rank[j]
makes no sense. You should swap them.
This was the code I had when took data structures class...
In the while condition it checks V... and inside the loop it moves the elements in V...
In your code you are comparing in one array and moving in the other... if you need the original position of elements you could just copy the array into a new one and sort the new array, instead of creating those ranks... (If you really need those ranks I'm pretty sure you could create while you sort)