Finding out where would a value "fit" in an Array? - arrays

I'm having a trouble with what should be a very simple algorithm, but for some reason my head is not working properly (too much work?)
I have an Array of numeric values: [ 10, 20, 30, 40, 100, 1000, 5000, 100000] I want to check which is the next "item" in the array.
For example,
given the number 10, my algorithm should return 10.
given the number 1, my algorithm should return 10
given the number 50, my algorithm should return 100.
given the number 99999999, my algorithm should return 100000
In pseudo-code I was thinking:
for previousValue, nextValue in values:
if ( previousValue < value && nextValue >= value ):
return nextValue
return values[max]
If anyone can point out to my exhausted brain what I'm missing it would be great. thanks!

Assuming the array is already sorted, your solution works fine. But to make it more clear I would rewrite it as follows:
prev = 0
for(v in values){
if(target > prev && target <= v)
return v
prev = v
}
return values[values.length-1]

In ruby :
find 0,values.length,val
def find left,right,val
if left == right || left > right then return values[left]
if val > values[(right + left)/2]
find (right + left)/2, right, val
else
find left, (right + left)/2, val
end
end

the array need not be sorted. sorting an array has O(nlogn) time complexity. You can check each element in the array in theta(n) time.
Assuming the array is arr and the comparison item is item and the array arr contains at least one element greater than or equal to item:
In java
public static int find_greater(int[] arr,int item)
{
int j=0;
int previous =0;
for(int i=0;i<arr.length;i++){
if(arr[i]>=item){
if(j==0){
previous = arr[i];
}else{
if(arr[i]<previous)
{
previous = arr[i];
}
}
j++;
}
}
return previous;
}
Here I go through the array and keep a variable previous which is the smallest number greater or equal item.
The running time for this procedure is theta(N) where N is arr.length.

I would probably represent this array as a tree.
To find out the closest biggest value, I will just look in the tree the same way I will do to find a key, and always keep track of my closest value. When I reach the end of the node, I return the closest value.
This is another alternative, compared to the other answers. You can check it in this thread How to find the closest element to a given key value in a binary search tree?

Related

Rebuild an array of integers after summing the digits of each element

We have an strictly increasing array of length n ( 1 < n < 500) . We sum the digits of each element to create a new array with each elements values is in range 1 to 500.The task is to rebuild the old array from the new one. since there might be more than one answer, we want the answers with the minimum value of the last element.
Example:
3 11 23 37 45 123 =>3 2 5 10 9 6
now from the second array, we can rebuild the original array in many different ways for instance:
12 20 23 37 54 60
from all the possible combinations, we need the one we minimum last element.
My Thoughts so far:
The brute force way is to find all possible permutations to create each number and then create all combinations possible of all numbers of the second array and find the combination with minimum last element. It is obvious that this is not a good choice.
Using this algorithm(with exponential time!) we can create all possible permutations of digits that sum to a number in the second arrays. Note that we know the original elements were less than 500 so we can limit the death of search of the algorithm.
One way I thought of that might find the answer faster is to:
start from the last element in the new arrays and find all possible
numbers that their digit sum resulted this element.
Then try to use the smallest amount in the last step for this element.
Now try to do the same with the second to last element. If the
minimum permutation value found for the second to last element is bigger
than the one found for the last element, backtrack to the last
element and try a larger permutation.
Do this until you get to the first element.
I think this is a greed solution but I'm not very sure about the time complexity. Also I want to know is there a better solution for this problem? like using dp?
For simplicity, let's have our sequence 1-based and the input sequence is called x.
We will also use an utility function, which returns the sum of the digits of a given number:
int sum(int x) {
int result = 0;
while (x > 0) {
result += x % 10;
x /= 10;
}
return result;
}
Let's assume that we are at index idx and try to set there some number called value (given that the sum of digits of value is x[idx]). If we do so, then what could we say about the previous number in the sequence? It should be strictly less than value.
So we already have a state for a potential dp approach - [idx, value], where idx is the index where we are currently at and value denotes the value we are trying to set on this index.
If the dp table holds boolean values, we will know we have found an answer if we have found a suitable number for the first number in the sequence. Therefore, if there is a path starting from the last row in the dp table and ends at row 0 then we'll know we have found an answer and we could then simply restore it.
Our recurrence function will be something like this:
f(idx, value) = OR {dp[idx - 1][value'], where sumOfDigits(value) = x[idx] and value' < value}
f(0, *) = true
Also, in order to restore the answer, we need to track the path. Once we set any dp[idx][value] cell to be true, then we can safe the value' to which we would like to jump in the previous table row.
Now let's code that one. I hope the code is self-explanatory:
boolean[][] dp = new boolean[n + 1][501];
int[][] prev = new int[n + 1][501];
for (int i = 0; i <= 500; i++) {
dp[0][i] = true;
}
for (int idx = 1; idx <= n; idx++) {
for (int value = 1; value <= 500; value++) {
if (sum(value) == x[idx]) {
for (int smaller = 0; smaller < value; smaller++) {
dp[idx][value] |= dp[idx - 1][smaller];
if (dp[idx][value]) {
prev[idx][value] = smaller;
break;
}
}
}
}
}
The prev table only keeps information about which is the smallest value', which we can use as previous to our idx in the resulting sequence.
Now, in order to restore the sequence, we can start from the last element. We would like it to be minimal, so we can find the first one that has dp[n][value] = true. Once we have such element, we then use the prev table to track down the values up to the first one:
int[] result = new int[n];
int idx = n - 1;
for (int i = 0; i <= 500; i++) {
if (dp[n][i]) {
int row = n, col = i;
while (row > 0) {
result[idx--] = col;
col = prev[row][col];
row--;
}
break;
}
}
for (int i = 0; i < n; i++) {
out.print(result[i]);
out.print(' ');
}
If we apply this on an input sequence:
3 2 5 10 9 6
we get
3 11 14 19 27 33
The time complexity is O(n * m * m), where n is the number of elements we have and m is the maximum possible value that an element could hold.
The space complexity is O(n * m) as this is dominated by the size of the dp and prev tables.
We can use a greedy algorithm: proceed through the array in order, setting each element to the least value that is greater than the previous element and has digits with the appropriate sum. (We can just iterate over the possible values and check the sums of their digits.) There's no need to consider any greater value than that, because increasing a given element will never make it possible to decrease a later element. So we don't need dynamic programming here.
We can calculate the sum of the digits of an integer m in O(log m) time, so the whole solution takes O(b log b) time, where b is the upper bound (500 in your example).

Given an unsorted integer array find numbers that are not searchable

Interview question from a friend
Given an unsorted integer array, how many number are not able to find using binary search?
For example, [2, 3, 4, 1, 5], only the number 1 can't be find using binary search, hence count = 1
[4,2,1,3,5] 4 and 4 and 2 are not searchable => binarySearch(arr, n) return a number that is not equal to num
Expected run time is O(n)
Can't think of an algorithm that can achieve O(n) time :(
Thought about building min and max arr, however, woudln't work as the subarray can mess it out again.
Already knew the O(nlogn) approach, it was obvious, just call binary search for each number and check.
I believe this code works fine. It does one single walk of each value in the list, so it is O(n).
function CountUnsearchable(list, minValue = -Infinity, maxValue=Infinity) {
if (list is empty) return 0;
let midPoint = mid point of "list"
let lowerCount = CountUnsearchable(left half of list, minValue, min(midPoint, maxValue));
let upperCount = CountUnsearchable(right half of list, max(minValue, midPoint), maxValue);
let midPointUnsearchable = 1 if midPoint less than minValue or greater than maxValue, otherwise 0;
return lowerCount + upperCount + midPointUnsearchable;
}
It works, because we walk the tree a bit like we would in a binary search, except at each node we take both paths, and simply track the maximum value that could have led us to take this path, and the minimum value that could have led us to take this path. That makes it simple to look at the current value and answer the question of whether it can be found via a binary search.
Try to create the following function:
def count_unsearchable(some_list, min_index=None, max_index=None, min_value=None, max_value=None):
"""How many elements of some_list are not searchable in the
range from min_index to max_index, assuming that by the time
we arrive our values are known to be in the range from
min_value to max_value. In all cases None means unbounded."""
pass #implementation TBD
It is possible to implement this function in a way that runs in time O(n). The reason why it is faster than the naive approach is that you are only making the recursive calls once per range, instead of once per element in that range.
Idea: Problem can be reworded as - find the count of numbers in the array which are greater than all numbers to their left and smaller than all numbers to their right. Further simplified, find the count of numbers which are greater than the max number to their left and smaller than the minimum number to their right.
Code: Java 11 | Time/Space: O(n)/O(n)
int binarySearchable(int[] nums) {
var n = nums.length;
var maxToLeft = new int[n + 1];
maxToLeft[0] = Integer.MIN_VALUE;
var minToRight = new int[n + 1];
minToRight[n] = Integer.MAX_VALUE;
for (var i = 1; i < n + 1; i++) {
maxToLeft[i] = Math.max(maxToLeft[i - 1], nums[i - 1]);
minToRight[n - i] = Math.min(minToRight[n + 1 - i], nums[n - i]);
}
for (var i = 0; i < n; i++)
if (nums[i] >= maxToLeft[i + 1] && nums[i] <= minToRight[i + 1])
count++;
return count;
}
TopCoder problem: https://community.topcoder.com/stat?c=problem_statement&pm=5869&rd=8078
Video explanation: https://www.youtube.com/watch?v=blICHR_ocDw
LeetCode discuss: https://leetcode.com/discuss/interview-question/352743/Google-or-Onsite-or-Guaranteed-Binary-Search-Numbers

Max score to reach end of array with step length

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;
}
}

Given an array, find out the next smaller element for each element

Given an array find the next smaller element in array for each element without changing the original order of the elements.
For example, suppose the given array is 4,2,1,5,3.
The resultant array would be 2,1,-1,3,-1.
I was asked this question in an interview, but i couldn't think of a solution better than the trivial O(n^2) solution.
Any approach that I could think of, i.e. making a binary search tree, or sorting the array, will distort the original order of the elements and hence lead to a wrong result.
Any help would be highly appreciated.
O(N) Algorithm
Initialize output array to all -1s.
Create an empty stack of indexes of items we have visited in the input array but don't yet know the answer for in the output array.
Iterate over each element in the input array:
Is it smaller than the item indexed by the top of the stack?
Yes. It is the first such element to be so. Fill in the corresponding element in our output array, remove the item from the stack, and try again until the stack is empty or the answer is no.
No. Continue to 3.2.
Add this index to the stack. Continue iteration from 3.
Python implementation
def find_next_smaller_elements(xs):
ys=[-1 for x in xs]
stack=[]
for i,x in enumerate(xs):
while len(stack)>0 and x<xs[stack[-1]]:
ys[stack.pop()]=x
stack.append(i)
return ys
>>> find_next_smaller_elements([4,2,1,5,3])
[2, 1, -1, 3, -1]
>>> find_next_smaller_elements([1,2,3,4,5])
[-1, -1, -1, -1, -1]
>>> find_next_smaller_elements([5,4,3,2,1])
[4, 3, 2, 1, -1]
>>> find_next_smaller_elements([1,3,5,4,2])
[-1, 2, 4, 2, -1]
>>> find_next_smaller_elements([6,4,2])
[4, 2, -1]
Explanation
How it works
This works because whenever we add an item to the stack, we know its value is greater or equal to every element in the stack already. When we visit an element in the array, we know that if it's lower than any item in the stack, it must be lower than the last item in the stack, because the last item must be the largest. So we don't need to do any kind of search on the stack, we can just consider the last item.
Note: You can skip the initialization step so long as you add a final step to empty the stack and use each remaining index to set the corresponding output array element to -1. It's just easier in Python to initialize it to -1s when creating it.
Time complexity
This is O(N). The main loop clearly visits each index once. Each index is added to the stack exactly once and removed at most once.
Solving as an interview question
This kind of question can be pretty intimidating in an interview, but I'd like to point out that (hopefully) an interviewer isn't going to expect the solution to spring from your mind fully-formed. Talk them through your thought process. Mine went something like this:
Is there some relationship between the positions of numbers and their next smaller number in the array? Does knowing some of them constrain what the others might possibly be?
If I were in front of a whiteboard I would probably sketch out the example array and draw lines between the elements. I might also draw them as a 2D bar graph - horizontal axis being position in input array and vertical axis being value.
I had a hunch this would show a pattern, but no paper to hand. I think the diagram would make it obvious. Thinking about it carefully, I could see that the lines would not overlap arbitrarily, but would only nest.
Around this point, it occurred to me that this is incredibly similar to the algorithm Python uses internally to transform indentation into INDENT and DEDENT virtual tokens, which I'd read about before. See "How does the compiler parse the indentation?" on this page: http://www.secnetix.de/olli/Python/block_indentation.hawk However, it wasn't until I actually worked out an algorithm that I followed up on this thought and determined that it was in fact the same, so I don't think it helped too much. Still, if you can see a similarity to some other problem you know, it's probably a good idea to mention it, and say how it's similar and how it's different.
From here the general shape of the stack-based algorithm became apparent, but I still needed to think about it a bit more to be sure it would work okay for those elements that have no subsequent smaller element.
Even if you don't come up with a working algorithm, try to let your interviewer see what you're thinking about. Often it is the thought process more than the answer that they're interested in. For a tough problem, failing to find the best solution but showing insight into the problem can be better than knowing a canned answer but not being able to give it much analysis.
Start making a BST, starting from the array end. For each value 'v' answer would be the last node "Right" that you took on your way to inserting 'v', of which you can easily keep track of in recursive or iterative version.
UPDATE:
Going by your requirements, you can approach this in a linear fashion:
If every next element is smaller than the current element(e.g. 6 5 4 3 2 1) you can process this linearly without requiring any extra memory. Interesting case arises when you start getting jumbled elements(e.g. 4 2 1 5 3), in which case you need to remember their order as long as you dont' get their 'smaller counterparts'.
A simple stack based approach goes like this:
Push the first element (a[0]) in a stack.
For each next element a[i], you peek into the stack and if value ( peek() ) is greater than the one in hand a[i], you got your next smaller number for that stack element (peek()) { and keep on popping the elements as long as peek() > a[i] }. Pop them out and print/store the corresponding value.
else, simply push back your a[i] into the stack.
In the end stack 'll contain those elements which never had a value smaller than them(to their right). You can fill in -1 for them in your outpput.
e.g. A=[4, 2, 1, 5, 3];
stack: 4
a[i] = 2, Pop 4, Push 2 (you got result for 4)
stack: 2
a[i] = 1, Pop 2, Push 1 (you got result for 2)
stack: 1
a[i] = 5
stack: 1 5
a[i] = 3, Pop 5, Push 3 (you got result for 5)
stack: 1 3
1,3 don't have any counterparts for them. so store -1 for them.
Assuming you meant first next element which is lower than the current element, here are 2 solutions -
Use sqrt(N) segmentation. Divide the array in sqrt(N) segments with each segment's length being sqrt(N). For each segment calculate its' minimum element using a loop. In this way, you have pre-calculated each segments' minimum element in O(N). Now, for each element, the next lower element can be in the same segment as that one or in any of the subsequent segments. So, first check all the next elements in the current segment. If all are larger, then loop through all the subsequent segments to find out which has an element lower than current element. If you couldn't find any, result would be -1. Otherwise, check every element of that segment to find out what is the first element lower than current element. Overall, algorithm complexity is O(N*sqrt(N)) or O(N^1.5).
You can achieve O(NlgN) using a segment tree with a similar approach.
Sort the array ascending first (keeping original position of the elements as satellite data). Now, assuming each element of the array is distinct, for each element, we will need to find the lowest original position on the left side of that element. It is a classic RMQ (Range Min Query) problem and can be solved in many ways including a O(N) one. As we need to sort first, overall complexity is O(NlogN). You can learn more about RMQ in a TopCoder tutorial.
For some reasons, I find it easier to reason about "previous smaller element", aka "all nearest smaller elements". Thus applied backward gives the "next smaller".
For the record, a Python implementation in O(n) time, O(1) space (i.e. without stack), supporting negative values in the array :
def next_smaller(l):
""" Return positions of next smaller items """
res = [None] * len(l)
for i in range(len(l)-2,-1,-1):
j=i+1
while j is not None and (l[j] > l[i]):
j = res[j]
res[i] = j
return res
def next_smaller_elements(l):
""" Return next smaller items themselves """
res = next_smaller(l)
return [l[i] if i is not None else None for i in res]
Here is the javascript code . This video explains the Algo better
function findNextSmallerElem(source){
let length = source.length;
let outPut = [...Array(length)].map(() => -1);
let stack = [];
for(let i = 0 ; i < length ; i++){
let stackTopVal = stack[ stack.length - 1] && stack[ stack.length - 1].val;
// If stack is empty or current elem is greater than stack top
if(!stack.length || source[i] > stackTopVal ){
stack.push({ val: source[i], ind: i} );
} else {
// While stacktop is greater than current elem , keep popping
while( source[i] < (stack[ stack.length - 1] && stack[ stack.length - 1].val) ){
outPut[stack.pop().ind] = source[i];
}
stack.push({ val: source[i], ind: i} );
}
}
return outPut;
}
Output -
findNextSmallerElem([98,23,54,12,20,7,27])
[23, 12, 12, 7, 7, -1, -1]
Time complexity O(N), space complexity O(N).
Clean solution on java keeping order of the array:
public static int[] getNGE(int[] a) {
var s = new Stack<Pair<Integer, Integer>>();
int n = a.length;
var result = new int[n];
s.push(Pair.of(0, a[0]));
for (int i = 1; i < n; i++) {
while (!s.isEmpty() && s.peek().v2 > a[i]) {
var top = s.pop();
result[top.v1] = a[i];
}
s.push(Pair.of(i, a[i]));
}
while (!s.isEmpty()) {
var top = s.pop();
result[top.v1] = -1;
}
return result;
}
static class Pair<K, V> {
K v1;
V v2;
public static <K, V> Pair<K, V> of (K v1, V v2) {
Pair p = new Pair();
p.v1 = v1;
p.v2 = v2;
return p;
}
}
Here is an observation that I think can be made into an O(n log n) solution. Suppose you have the answer for the last k elements of the array. What would you need in order to figure out the value for the element just before this? You can think of the last k elements as being split into a series of ranges, each of which starts at some element and continues forward until it hits a smaller element. These ranges must be in descending order, so you could think about doing a binary search over them to find the first interval smaller than that element. You could then update the ranges to factor in this new element.
Now, how best to represent this? The best way I've thought of is to use a splay tree whose keys are the elements defining these ranges and whose values are the index at which they start. You can then in time O(log n) amortized do a predecessor search to find the predecessor of the current element. This finds the earliest value smaller than the current. Then, in amortized O(log n) time, insert the current element into the tree. This represents defining a new range from that element forward. To discard all ranges this supercedes, you then cut the right child of the new node, which because this is a splay tree is at the root, from the tree.
Overall, this does O(n) iterations of an O(log n) process for total O(n lg n).
Here is a O(n) algorithm using DP (actually O(2n) ):
int n = array.length();
The array min[] record the minimum number found from index i until the end of the array.
int[] min = new int[n];
min[n-1] = array[n-1];
for(int i=n-2; i>=0; i--)
min[i] = Math.min(min[i+1],array[i]);
Search and compare through the original array and min[].
int[] result = new int[n];
result[n-1] = -1;
for(int i=0; i<n-1; i++)
result[i] = min[i+1]<array[i]?min[i+1]:-1;
Here is the new solution to find "next smaller element":
int n = array.length();
int[] answer = new int[n];
answer[n-1] = -1;
for(int i=0; i<n-1; i++)
answer[i] = array[i+1]<array[i]?array[i+1]:-1;
All that is actually not required i think
case 1: a,b
answer : -a+b
case 2: a,b,c
answer : a-2b+c
case 3: a,b,c,d
answer : -a+3b-3c+d
case 4 :a,b,c,d,e
answer : a-4b+6c-4d+e
.
.
.
recognize the pattern in it?
it is the pascal's triangle!
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
so it can be calculated using Nth row of pascal's triangle!
with alternate + ans - for odd even levels!
it is O(1)
You can solve this in O(n) runtime with O(n) space complexity.
Start with a Stack and keep pushing elements till you find arr[i] such that arr[i] < stack.top element. Then store this index .
Code Snippet:
vector<int> findNext(vector<int> values) {
stack<int> st;
vector<int> nextSmall(values.size(), -1);
st.push(0);
for (int i = 1; i < values.size(); i++) {
while (!st.empty() && values[i] < values[st.top()]) {
// change values[i] < values[st.top()] to values[i] > values[st.top()] to find the next greater element.
nextSmall[st.top()] = i;
st.pop();
}
st.push(i);
}
return nextSmall;
}
Solution with O(1) space complexity and O(n) time complexity.
void replace_next_smallest(int a[], int n)
{
int ns = a[n - 1];
for (int i = n - 1; i >= 0; i--) {
if (i == n - 1) {
a[i] = -1;
}
else if (a[i] > ns) {
int t = ns;
ns = a[i];
a[i] = t;
}
else if (a[i] == ns) {
a[i] = a[i + 1];
}
else {
ns = a[i];
a[i] = -1;
}
}
}
Solution With O(n) Time Complexity and O(1) Space Complexity. This Solution is not complex to understand and implemented without stack.
def min_secMin(a,n):
min = a[0]
sec_min = a[1]
for i in range(1,n):
if(a[i]<min):
sec_min = min
min = a[i]
if(a[i]>min and a[i]<sec_min):
sec_min = a[i]
return min,sec_min
Given an array find the next smaller element in array for each element without changing the original order of the elements.
where arr is the array and n is length of the array..
Using Python logic,
def next_smallest_array(arr,n):
for i in range(0,n-1,1):
if arr[i]>arr[i+1]:
arr[i]=arr[i+1]
else:
arr[i]=-1
arr[n-1]=-1
return arr
Find_next_smaller_elements([4,2,1,5,3])
Output is [2, 1, -1, 3, -1]
Find_next_smaller_elements([1,2,3,4,5])
Output is [-1, -1, -1, -1, -1]

Find the Smallest Integer Not in a List

An interesting interview question that a colleague of mine uses:
Suppose that you are given a very long, unsorted list of unsigned 64-bit integers. How would you find the smallest non-negative integer that does not occur in the list?
FOLLOW-UP: Now that the obvious solution by sorting has been proposed, can you do it faster than O(n log n)?
FOLLOW-UP: Your algorithm has to run on a computer with, say, 1GB of memory
CLARIFICATION: The list is in RAM, though it might consume a large amount of it. You are given the size of the list, say N, in advance.
If the datastructure can be mutated in place and supports random access then you can do it in O(N) time and O(1) additional space. Just go through the array sequentially and for every index write the value at the index to the index specified by value, recursively placing any value at that location to its place and throwing away values > N. Then go again through the array looking for the spot where value doesn't match the index - that's the smallest value not in the array. This results in at most 3N comparisons and only uses a few values worth of temporary space.
# Pass 1, move every value to the position of its value
for cursor in range(N):
target = array[cursor]
while target < N and target != array[target]:
new_target = array[target]
array[target] = target
target = new_target
# Pass 2, find first location where the index doesn't match the value
for cursor in range(N):
if array[cursor] != cursor:
return cursor
return N
Here's a simple O(N) solution that uses O(N) space. I'm assuming that we are restricting the input list to non-negative numbers and that we want to find the first non-negative number that is not in the list.
Find the length of the list; lets say it is N.
Allocate an array of N booleans, initialized to all false.
For each number X in the list, if X is less than N, set the X'th element of the array to true.
Scan the array starting from index 0, looking for the first element that is false. If you find the first false at index I, then I is the answer. Otherwise (i.e. when all elements are true) the answer is N.
In practice, the "array of N booleans" would probably be encoded as a "bitmap" or "bitset" represented as a byte or int array. This typically uses less space (depending on the programming language) and allows the scan for the first false to be done more quickly.
This is how / why the algorithm works.
Suppose that the N numbers in the list are not distinct, or that one or more of them is greater than N. This means that there must be at least one number in the range 0 .. N - 1 that is not in the list. So the problem of find the smallest missing number must therefore reduce to the problem of finding the smallest missing number less than N. This means that we don't need to keep track of numbers that are greater or equal to N ... because they won't be the answer.
The alternative to the previous paragraph is that the list is a permutation of the numbers from 0 .. N - 1. In this case, step 3 sets all elements of the array to true, and step 4 tells us that the first "missing" number is N.
The computational complexity of the algorithm is O(N) with a relatively small constant of proportionality. It makes two linear passes through the list, or just one pass if the list length is known to start with. There is no need to represent the hold the entire list in memory, so the algorithm's asymptotic memory usage is just what is needed to represent the array of booleans; i.e. O(N) bits.
(By contrast, algorithms that rely on in-memory sorting or partitioning assume that you can represent the entire list in memory. In the form the question was asked, this would require O(N) 64-bit words.)
#Jorn comments that steps 1 through 3 are a variation on counting sort. In a sense he is right, but the differences are significant:
A counting sort requires an array of (at least) Xmax - Xmin counters where Xmax is the largest number in the list and Xmin is the smallest number in the list. Each counter has to be able to represent N states; i.e. assuming a binary representation it has to have an integer type (at least) ceiling(log2(N)) bits.
To determine the array size, a counting sort needs to make an initial pass through the list to determine Xmax and Xmin.
The minimum worst-case space requirement is therefore ceiling(log2(N)) * (Xmax - Xmin) bits.
By contrast, the algorithm presented above simply requires N bits in the worst and best cases.
However, this analysis leads to the intuition that if the algorithm made an initial pass through the list looking for a zero (and counting the list elements if required), it would give a quicker answer using no space at all if it found the zero. It is definitely worth doing this if there is a high probability of finding at least one zero in the list. And this extra pass doesn't change the overall complexity.
EDIT: I've changed the description of the algorithm to use "array of booleans" since people apparently found my original description using bits and bitmaps to be confusing.
Since the OP has now specified that the original list is held in RAM and that the computer has only, say, 1GB of memory, I'm going to go out on a limb and predict that the answer is zero.
1GB of RAM means the list can have at most 134,217,728 numbers in it. But there are 264 = 18,446,744,073,709,551,616 possible numbers. So the probability that zero is in the list is 1 in 137,438,953,472.
In contrast, my odds of being struck by lightning this year are 1 in 700,000. And my odds of getting hit by a meteorite are about 1 in 10 trillion. So I'm about ten times more likely to be written up in a scientific journal due to my untimely death by a celestial object than the answer not being zero.
As pointed out in other answers you can do a sort, and then simply scan up until you find a gap.
You can improve the algorithmic complexity to O(N) and keep O(N) space by using a modified QuickSort where you eliminate partitions which are not potential candidates for containing the gap.
On the first partition phase, remove duplicates.
Once the partitioning is complete look at the number of items in the lower partition
Is this value equal to the value used for creating the partition?
If so then it implies that the gap is in the higher partition.
Continue with the quicksort, ignoring the lower partition
Otherwise the gap is in the lower partition
Continue with the quicksort, ignoring the higher partition
This saves a large number of computations.
To illustrate one of the pitfalls of O(N) thinking, here is an O(N) algorithm that uses O(1) space.
for i in [0..2^64):
if i not in list: return i
print "no 64-bit integers are missing"
Since the numbers are all 64 bits long, we can use radix sort on them, which is O(n). Sort 'em, then scan 'em until you find what you're looking for.
if the smallest number is zero, scan forward until you find a gap. If the smallest number is not zero, the answer is zero.
For a space efficient method and all values are distinct you can do it in space O( k ) and time O( k*log(N)*N ). It's space efficient and there's no data moving and all operations are elementary (adding subtracting).
set U = N; L=0
First partition the number space in k regions. Like this:
0->(1/k)*(U-L) + L, 0->(2/k)*(U-L) + L, 0->(3/k)*(U-L) + L ... 0->(U-L) + L
Find how many numbers (count{i}) are in each region. (N*k steps)
Find the first region (h) that isn't full. That means count{h} < upper_limit{h}. (k steps)
if h - count{h-1} = 1 you've got your answer
set U = count{h}; L = count{h-1}
goto 2
this can be improved using hashing (thanks for Nic this idea).
same
First partition the number space in k regions. Like this:
L + (i/k)->L + (i+1/k)*(U-L)
inc count{j} using j = (number - L)/k (if L < number < U)
find first region (h) that doesn't have k elements in it
if count{h} = 1 h is your answer
set U = maximum value in region h L = minimum value in region h
This will run in O(log(N)*N).
I'd just sort them then run through the sequence until I find a gap (including the gap at the start between zero and the first number).
In terms of an algorithm, something like this would do it:
def smallest_not_in_list(list):
sort(list)
if list[0] != 0:
return 0
for i = 1 to list.last:
if list[i] != list[i-1] + 1:
return list[i-1] + 1
if list[list.last] == 2^64 - 1:
assert ("No gaps")
return list[list.last] + 1
Of course, if you have a lot more memory than CPU grunt, you could create a bitmask of all possible 64-bit values and just set the bits for every number in the list. Then look for the first 0-bit in that bitmask. That turns it into an O(n) operation in terms of time but pretty damned expensive in terms of memory requirements :-)
I doubt you could improve on O(n) since I can't see a way of doing it that doesn't involve looking at each number at least once.
The algorithm for that one would be along the lines of:
def smallest_not_in_list(list):
bitmask = mask_make(2^64) // might take a while :-)
mask_clear_all (bitmask)
for i = 1 to list.last:
mask_set (bitmask, list[i])
for i = 0 to 2^64 - 1:
if mask_is_clear (bitmask, i):
return i
assert ("No gaps")
Sort the list, look at the first and second elements, and start going up until there is a gap.
We could use a hash table to hold the numbers. Once all numbers are done, run a counter from 0 till we find the lowest. A reasonably good hash will hash and store in constant time, and retrieves in constant time.
for every i in X // One scan Θ(1)
hashtable.put(i, i); // O(1)
low = 0;
while (hashtable.get(i) <> null) // at most n+1 times
low++;
print low;
The worst case if there are n elements in the array, and are {0, 1, ... n-1}, in which case, the answer will be obtained at n, still keeping it O(n).
You can do it in O(n) time and O(1) additional space, although the hidden factor is quite large. This isn't a practical way to solve the problem, but it might be interesting nonetheless.
For every unsigned 64-bit integer (in ascending order) iterate over the list until you find the target integer or you reach the end of the list. If you reach the end of the list, the target integer is the smallest integer not in the list. If you reach the end of the 64-bit integers, every 64-bit integer is in the list.
Here it is as a Python function:
def smallest_missing_uint64(source_list):
the_answer = None
target = 0L
while target < 2L**64:
target_found = False
for item in source_list:
if item == target:
target_found = True
if not target_found and the_answer is None:
the_answer = target
target += 1L
return the_answer
This function is deliberately inefficient to keep it O(n). Note especially that the function keeps checking target integers even after the answer has been found. If the function returned as soon as the answer was found, the number of times the outer loop ran would be bound by the size of the answer, which is bound by n. That change would make the run time O(n^2), even though it would be a lot faster.
Thanks to egon, swilden, and Stephen C for my inspiration. First, we know the bounds of the goal value because it cannot be greater than the size of the list. Also, a 1GB list could contain at most 134217728 (128 * 2^20) 64-bit integers.
Hashing part
I propose using hashing to dramatically reduce our search space. First, square root the size of the list. For a 1GB list, that's N=11,586. Set up an integer array of size N. Iterate through the list, and take the square root* of each number you find as your hash. In your hash table, increment the counter for that hash. Next, iterate through your hash table. The first bucket you find that is not equal to it's max size defines your new search space.
Bitmap part
Now set up a regular bit map equal to the size of your new search space, and again iterate through the source list, filling out the bitmap as you find each number in your search space. When you're done, the first unset bit in your bitmap will give you your answer.
This will be completed in O(n) time and O(sqrt(n)) space.
(*You could use use something like bit shifting to do this a lot more efficiently, and just vary the number and size of buckets accordingly.)
Well if there is only one missing number in a list of numbers, the easiest way to find the missing number is to sum the series and subtract each value in the list. The final value is the missing number.
int i = 0;
while ( i < Array.Length)
{
if (Array[i] == i + 1)
{
i++;
}
if (i < Array.Length)
{
if (Array[i] <= Array.Length)
{//SWap
int temp = Array[i];
int AnoTemp = Array[temp - 1];
Array[temp - 1] = temp;
Array[i] = AnoTemp;
}
else
i++;
}
}
for (int j = 0; j < Array.Length; j++)
{
if (Array[j] > Array.Length)
{
Console.WriteLine(j + 1);
j = Array.Length;
}
else
if (j == Array.Length - 1)
Console.WriteLine("Not Found !!");
}
}
Here's my answer written in Java:
Basic Idea:
1- Loop through the array throwing away duplicate positive, zeros, and negative numbers while summing up the rest, getting the maximum positive number as well, and keep the unique positive numbers in a Map.
2- Compute the sum as max * (max+1)/2.
3- Find the difference between the sums calculated at steps 1 & 2
4- Loop again from 1 to the minimum of [sums difference, max] and return the first number that is not in the map populated in step 1.
public static int solution(int[] A) {
if (A == null || A.length == 0) {
throw new IllegalArgumentException();
}
int sum = 0;
Map<Integer, Boolean> uniqueNumbers = new HashMap<Integer, Boolean>();
int max = A[0];
for (int i = 0; i < A.length; i++) {
if(A[i] < 0) {
continue;
}
if(uniqueNumbers.get(A[i]) != null) {
continue;
}
if (A[i] > max) {
max = A[i];
}
uniqueNumbers.put(A[i], true);
sum += A[i];
}
int completeSum = (max * (max + 1)) / 2;
for(int j = 1; j <= Math.min((completeSum - sum), max); j++) {
if(uniqueNumbers.get(j) == null) { //O(1)
return j;
}
}
//All negative case
if(uniqueNumbers.isEmpty()) {
return 1;
}
return 0;
}
As Stephen C smartly pointed out, the answer must be a number smaller than the length of the array. I would then find the answer by binary search. This optimizes the worst case (so the interviewer can't catch you in a 'what if' pathological scenario). In an interview, do point out you are doing this to optimize for the worst case.
The way to use binary search is to subtract the number you are looking for from each element of the array, and check for negative results.
I like the "guess zero" apprach. If the numbers were random, zero is highly probable. If the "examiner" set a non-random list, then add one and guess again:
LowNum=0
i=0
do forever {
if i == N then leave /* Processed entire array */
if array[i] == LowNum {
LowNum++
i=0
}
else {
i++
}
}
display LowNum
The worst case is n*N with n=N, but in practice n is highly likely to be a small number (eg. 1)
I am not sure if I got the question. But if for list 1,2,3,5,6 and the missing number is 4, then the missing number can be found in O(n) by:
(n+2)(n+1)/2-(n+1)n/2
EDIT: sorry, I guess I was thinking too fast last night. Anyway, The second part should actually be replaced by sum(list), which is where O(n) comes. The formula reveals the idea behind it: for n sequential integers, the sum should be (n+1)*n/2. If there is a missing number, the sum would be equal to the sum of (n+1) sequential integers minus the missing number.
Thanks for pointing out the fact that I was putting some middle pieces in my mind.
Well done Ants Aasma! I thought about the answer for about 15 minutes and independently came up with an answer in a similar vein of thinking to yours:
#define SWAP(x,y) { numerictype_t tmp = x; x = y; y = tmp; }
int minNonNegativeNotInArr (numerictype_t * a, size_t n) {
int m = n;
for (int i = 0; i < m;) {
if (a[i] >= m || a[i] < i || a[i] == a[a[i]]) {
m--;
SWAP (a[i], a[m]);
continue;
}
if (a[i] > i) {
SWAP (a[i], a[a[i]]);
continue;
}
i++;
}
return m;
}
m represents "the current maximum possible output given what I know about the first i inputs and assuming nothing else about the values until the entry at m-1".
This value of m will be returned only if (a[i], ..., a[m-1]) is a permutation of the values (i, ..., m-1). Thus if a[i] >= m or if a[i] < i or if a[i] == a[a[i]] we know that m is the wrong output and must be at least one element lower. So decrementing m and swapping a[i] with the a[m] we can recurse.
If this is not true but a[i] > i then knowing that a[i] != a[a[i]] we know that swapping a[i] with a[a[i]] will increase the number of elements in their own place.
Otherwise a[i] must be equal to i in which case we can increment i knowing that all the values of up to and including this index are equal to their index.
The proof that this cannot enter an infinite loop is left as an exercise to the reader. :)
The Dafny fragment from Ants' answer shows why the in-place algorithm may fail. The requires pre-condition describes that the values of each item must not go beyond the bounds of the array.
method AntsAasma(A: array<int>) returns (M: int)
requires A != null && forall N :: 0 <= N < A.Length ==> 0 <= A[N] < A.Length;
modifies A;
{
// Pass 1, move every value to the position of its value
var N := A.Length;
var cursor := 0;
while (cursor < N)
{
var target := A[cursor];
while (0 <= target < N && target != A[target])
{
var new_target := A[target];
A[target] := target;
target := new_target;
}
cursor := cursor + 1;
}
// Pass 2, find first location where the index doesn't match the value
cursor := 0;
while (cursor < N)
{
if (A[cursor] != cursor)
{
return cursor;
}
cursor := cursor + 1;
}
return N;
}
Paste the code into the validator with and without the forall ... clause to see the verification error. The second error is a result of the verifier not being able to establish a termination condition for the Pass 1 loop. Proving this is left to someone who understands the tool better.
Here's an answer in Java that does not modify the input and uses O(N) time and N bits plus a small constant overhead of memory (where N is the size of the list):
int smallestMissingValue(List<Integer> values) {
BitSet bitset = new BitSet(values.size() + 1);
for (int i : values) {
if (i >= 0 && i <= values.size()) {
bitset.set(i);
}
}
return bitset.nextClearBit(0);
}
def solution(A):
index = 0
target = []
A = [x for x in A if x >=0]
if len(A) ==0:
return 1
maxi = max(A)
if maxi <= len(A):
maxi = len(A)
target = ['X' for x in range(maxi+1)]
for number in A:
target[number]= number
count = 1
while count < maxi+1:
if target[count] == 'X':
return count
count +=1
return target[count-1] + 1
Got 100% for the above solution.
1)Filter negative and Zero
2)Sort/distinct
3)Visit array
Complexity: O(N) or O(N * log(N))
using Java8
public int solution(int[] A) {
int result = 1;
boolean found = false;
A = Arrays.stream(A).filter(x -> x > 0).sorted().distinct().toArray();
//System.out.println(Arrays.toString(A));
for (int i = 0; i < A.length; i++) {
result = i + 1;
if (result != A[i]) {
found = true;
break;
}
}
if (!found && result == A.length) {
//result is larger than max element in array
result++;
}
return result;
}
An unordered_set can be used to store all the positive numbers, and then we can iterate from 1 to length of unordered_set, and see the first number that does not occur.
int firstMissingPositive(vector<int>& nums) {
unordered_set<int> fre;
// storing each positive number in a hash.
for(int i = 0; i < nums.size(); i +=1)
{
if(nums[i] > 0)
fre.insert(nums[i]);
}
int i = 1;
// Iterating from 1 to size of the set and checking
// for the occurrence of 'i'
for(auto it = fre.begin(); it != fre.end(); ++it)
{
if(fre.find(i) == fre.end())
return i;
i +=1;
}
return i;
}
Solution through basic javascript
var a = [1, 3, 6, 4, 1, 2];
function findSmallest(a) {
var m = 0;
for(i=1;i<=a.length;i++) {
j=0;m=1;
while(j < a.length) {
if(i === a[j]) {
m++;
}
j++;
}
if(m === 1) {
return i;
}
}
}
console.log(findSmallest(a))
Hope this helps for someone.
With python it is not the most efficient, but correct
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import datetime
# write your code in Python 3.6
def solution(A):
MIN = 0
MAX = 1000000
possible_results = range(MIN, MAX)
for i in possible_results:
next_value = (i + 1)
if next_value not in A:
return next_value
return 1
test_case_0 = [2, 2, 2]
test_case_1 = [1, 3, 44, 55, 6, 0, 3, 8]
test_case_2 = [-1, -22]
test_case_3 = [x for x in range(-10000, 10000)]
test_case_4 = [x for x in range(0, 100)] + [x for x in range(102, 200)]
test_case_5 = [4, 5, 6]
print("---")
a = datetime.datetime.now()
print(solution(test_case_0))
print(solution(test_case_1))
print(solution(test_case_2))
print(solution(test_case_3))
print(solution(test_case_4))
print(solution(test_case_5))
def solution(A):
A.sort()
j = 1
for i, elem in enumerate(A):
if j < elem:
break
elif j == elem:
j += 1
continue
else:
continue
return j
this can help:
0- A is [5, 3, 2, 7];
1- Define B With Length = A.Length; (O(1))
2- initialize B Cells With 1; (O(n))
3- For Each Item In A:
if (B.Length <= item) then B[Item] = -1 (O(n))
4- The answer is smallest index in B such that B[index] != -1 (O(n))

Resources