Sample input:
5
1
2
1
3
1
First number = # of members in the set, N
Following N numbers = ID's of the members
I'd have to find the size of the longest consecutive sequence of distinct integers in the set. In this instance, it'd be the sequence of {2, 1, 3}, so the output would be 3.
My brute force solution would be to generate a sliding window that shrinks in size by 1 every iteration. The initial size is the size of the input. So, for the sample input, it'd evaluate {1, 2, 1, 3, 1} first, if set is not all unique, then decrease the window to 4, and evaluate {1, 2, 1, 3}, {2, 1, 3, 1}. Keep going until you found a set that's unique.
For one, I believe this algorithm would be O(N^2) time. So, how might I optimize this?
You can use a hash table for an O(N) solution. Simply put, keep track of the last index of each unique element and the last time a repetition happens. The maximum between these two variables at each index is how far back you can go at that index without repeating.
For sake of completeness here is a straightforward and (hopefully) well commented python implementation:
def longestDistinctSequence(iterable):
res = 0
# store the indices of each unique element
hashmap = {}
# keep track of how back you can go before you run into a repetition
last_repeat = 0
# loop through each index and item
for index, item in enumerate(iterable):
# how back you can go before you can run into a repetition is the max of:
# 1. The last occurence of this element (zero if this is first instance)
# 2. The last_repeat of the last iteration
last_repeat = max(hashmap.get(item, 0), last_repeat)
# calculate the global maximum
res = max(res, index - last_repeat + 1)
# update the hashmap to reflect the repetition of this element
hashmap[item] = index + 1
return res
Related
Today I had Interview where I was asked one problem, and I couldnt even understand.
Problem:
Given one array 𝑎 consisting of 𝑛 integers.
Get at least 𝑘 equal elements in the array 𝑎.
While calculating, you can do below two operations
Take one of the minimum elements of the array and increase its value by one (more formally, if the minimum value of 𝑎 is 𝑚𝑛 then you choose such index 𝑖 that 𝑎𝑖=𝑚𝑛 and set 𝑎𝑖:=𝑎𝑖+1);
take one of the maximum elements of the array and decrease its value by one (more formally, if the maximum value of 𝑎 is 𝑚𝑥 then you choose such index 𝑖 that 𝑎𝑖=𝑚𝑥 and set 𝑎𝑖:=𝑎𝑖−1).
Calculate the minimum number of moves required to obtain at least 𝑘 equal elements in the array.
Can anyone help me to undestand, what's a actual problem is about so that I could write code ?
To answer your question directly, which is "Help me understand the problem":
For example, here's your array:
{1,2,5,7,8,3}
Now, you can do only those two operations:
Find the minimum element and increase it:
{2,2,5,7,8,3} // <-- increased 1
Decrease the maximum element:
{2,2,5,7,7,3} // <-- decreased 8
And the question now is: What is the minimum number of moves to make this array contain k identical numbers?
So if k = 3 and the array is like the above, then one of the solutions would be to run operation 1 three times:
Before any moves:
{1,2,5,7,8,3}
After first move:
{2,2,5,7,8,3} // <-- `1` changed to `2`
After second move:
{3,2,5,7,8,3} // <-- `2` changed to `3`
After third move:
{3,3,5,7,8,3} // <-- `2` changed to `3`
So the resulting array would be:
{3,3,5,7,8,3}
Do you understand the problem now?
In terms of the algorithm to find k equal elements:
At any given step in the algorithm, there are some number of equal elements, say j. If j >= k, you're done. Otherwise, you need to choose some combination of the moves to increase j.
You don't have much flexibility in what you can do. You can only reduce a maximal element, or increase a minimal element.
Let's say there is a unique maximal element (i.e. when there is only one element in the array equal to the maximum element). You can increase j by (at least) 1 by reducing that until it equals the second-largest element.
Similarly, you can increase j by (at least) 1 by increasing a unique minimal element (i.e. when there is only one element in the array equal to the maximum element) until it equals the second-smallest element.
Therefore, the smallest number of moves to achieve the (at least) 1 increase is the one out of [decrease the maximal; increase the maximal] which achieve this.
For example, in the array [1, 3, 5, 6], your choices are:
Take 2 moves to increase the 1 so it equals 3: [3, 3, 5, 6]
Take 1 move to decrease the 6 so it equals 5: [1, 3, 5, 5]
In this case, you increase j by 2 most cheaply by decreasing the 6.
But after doing that, there are equal maximal elements: there are two elements equal to 5. By decreasing one of these, you decrease j by 2 (because [1, 3, 4, 5] has no equal elements); but by decreasing the maximum again, you make j the same as it was before (because [1, 3, 4, 4] again has 2 equal elements). So, you've got to do some work to "stand still" (that is, get j back to its previous value), before you can then decrease the maximum to increase j.
(Similarly for the minimal elements)
So, your algorithm can find the (greedy) minimum number of steps to make j == k by deciding whether to [decrease the maximal elements] or [increase the minimal element]. I don't know if the greedy minimum is actually the minimum, but I can't think of an obvious algorithm to find it non-greedily, other than searching all possibilities, which would have awful computational complexity, so is probably not what this interview was looking for.
So if there's an array like [2, 3, 5, 7, 11], the differences would be 1, 2, 2, 4, therefore you'd return 2.
Brute force would be to just iterate over the initial structure, store each calculated difference in a new structure, and count the most number of occurrences of an element in that new structure.
I'm wondering if there's a different, better way to do this, or if that solution would be considered efficient?
That solution will be efficient, if implemented "properly". If you're using a package with a vectorized array type, then use the shift operation to get the vector of differences. That's O(N) with or without the vectorization.
A second linear pass will find the mode of the array, yielding your final answer. Keep a simple array to count how many times each value appears:
for item in diff_array:
mode_ct[item] += 1
Then find the max of mode_ct; return its index.
I have an algorithm that checks whether or not a game row can be solved. The game row is an array of positive integers, where the last element is 0. The game marker starts at index 0 and moves along the array the number of steps indicated by the integer it is positioned at.
For example, [1, 1, 0] returns true, while [1, 2, 0] returns false.
The marker can also move left or right in order to solve the game.
That is, [3, 3, 2, 2, 0] is solvable.
Algorithm recursiveSolvable(gameArray, index)
if index = gameArray.length - 1 // the last element has been reached
return true
if index < 0 || index >= gameArray.length || arrayList.contains(index)
return false
arrayList.add(index) // store visited indices to avoid infinite loop
else
// move towards the goal (last element) if possible
// otherwise, trace back steps to find another way
return recursiveSolvable(gameArray, index + gameArray[index])
|| recursiveSolvable(gameArray, index - gameArray[index])
I have tried with a few examples of game rows and calculated the time complexity in the worst case:
[2, 0] has 2 recursive calls where the first one returns false, and the second one as well
[1, 1, 2, 0] has 5:
go right || go left - false
|
go right || go left - false
|
go right || go left - false (because index 0 has been visited)
|
false (then go left)
Other cases gave me numbers that I couldn't find the relation with the input size, but when I run the program with input size n = 100, the output is shown instantly, so I assume the time complexity is not O(2^n) (like binary recursion). I am more leaning towards O(n)...
As for the space complexity, I have no idea how to find it.
The run time is indeed more like O(n). This is because each index position is investigated only once (due to the test with the arrayList).
The exact bound depends also on the data structure used for arrayList. Is it really a List or a HashSet?
The space complexity is O(n) for the same reason. There can only be one incarnation of the recursive method for each index position.
You have k lists of sorted integers. Find the smallest range that includes at least one number from each of the k lists.
For example,
List 1: [4, 10, 13, 14]
List 2: [0, 9, 15, 18]
List 3: [5, 18, 22, 30]
The smallest range here would be [14, 18] as it contains 14 from list 1, 15 from list 2, and 18 from list 3.
MY approach is:
Just use a MinHeap and insert the first elements from K lists
Remove the the min element and add the next element from the corresponding list
Simultaneously track the max and min value so that we can calculate the minimum range
But the only issue I am facing is: Suppose for one list there is no more elements left than should I finish there or should I continue?
Very nice O(n log n) algorithm!
You can finish there because you will never find the better interval fulfilling the given condition "range that includes at least one number from each of the k lists".
Suppose you are leaving current minimum m (the last element from some list) and instead you are removing something (not minimum) from another list. In that case the range can only grow (because minimum of the range is determined by m). So there is no point in doing that and you can just stop your algorithm.
No, that is not your terminating condition. Look at this example:
1: [0]
2: [1]
The range is quite clearly [0,1], but if you stopped as soon as you detected an empty list, you would return [0,0].
So, you can only stop once you know you have seen values from all k lists and one of the lists has run out of items. If you are keeping track of the min- and max-values for each list separately, this should be pretty easy, seeing as you can just make sure there is some min- and max-value for each list.
When I put a integer list, how can I generate another random order but with constraint?
For example, I put integer 1, 2, 3, 4 into the collection and when I try to print result like be "1 2 3 4","1 2 4 3","1 3 2 4" ,"2 1 3 4",or "2 1 4 3"(1 must before 3, 2 must before 4)
thanks in advance
One thing you can consider is swapping elements at random. You could pick a random position in your collection, then swap the element in that position with the next element. This way, you can prevent swapping 1 with 3, or 2 with 4. You can do this repetitively, until the numbers are properly scrambled:
[1, 2, 3, 4] random number is 0, swap with element at position 1.
[2, 1, 3, 4] random number is 1, swap with element at position 2.
elements are 1 and 3, so don't swap.
[2, 1, 3, 4] random number is 2, swap with element at position 3.
[2, 1, 4, 3] etc.
If you'd like to generalize the constraint, you can simply change the condition. Instead of refusing to swap when the elements are either 1 and 3, or 2 and 4 (as in the example above), you could make sure the two elements at the positions to be swapped are not within 2 of each other, so something like if(b==a+2)continue;:
elements are 5 and 7, so don't swap.
if(7==5+2)continue; // ie don't swap.
What you've defined here is known as a partial order. You wish to generate a random permutation which still satisfies the partial order, i.e. a random linear extension.
Luckily, the Java API specifies Collections.shuffle, which implements the Fisher-Yates algorithm to generate a random permutation.
Unfortunately, the standard Java technique via Collections.sort is a comparison sort, and thus focused on total orders -- unlike the partial order we want. In fact, the Java API lacks a sorting algorithm we could use here.
One approach covered in "Generating Linear Extensions of Posets by Transpositions" involves that of swapping adjacent elements in the set in a fashion similar to Hassan's solution. This appears to be a functioning way for the localized problem at hand.
If you use it as a string then you could use this answer's algorithm to swap all the numbers
When you enter all the numbers then just concatenate them together. There is no need to treat them as numbers or strings. All you want to do is reorder them.
When you get the result you could then check to see if your constraints match and then print out another list. Something like this perhaps
private boolean isConstraintSatisfied(String wholeString, String firstNum, String secondNum){
return wholeString.indexOf(firstNum) <= wholeString.indexOf(secondNum);
}
Not the most elegant solution but I think it would work. For small input sets it shouldnt be too inefficient.