To clarify at the outset, this is not a homework, I was asked this question at a recent interview and drew a blank.
So I've the following array,
{1, 6, 3, 2, 9}
A change is step which increments any element by 1 and decrements any other element by 1. Thus 1 change could be like,
{2, 5, 3, 2, 9}
I'm allowed to make unlimited such changes, till I get maximum number of equal elements, thus the given array could become
{3, 3, 3, 3, 7} or {3, 4, 4, 4, 4}
Beyond this point more changes will not get any more elements equal. The question is thus, making unlimited changes, what is the maximum number of elements that can be made equal.
Thus the answer for the above array is 4. (Note there are two cases, in either case though the answer is 4)
Another example will be the array,
{1, 4, 1}
In which case we can make changes to get to
{2, 2, 2}
Thus the answer in this case is 3.
Can someone help me with an approach to get started. I'm still drawing a blank.
This seems to be a mathematical problem rather than a computer related one. Since every "Change" increments one element and decrements another, the sum of all the values in the array is constant.
This means that you can get all n elements of the array identical if and only if the sum of all elements can be evenly divided by n. Otherwise one of the elements must take another value to get n-1 equal elements.
By the way, your answers {3, 3, 3, 3, 7} and {3, 4, 4, 4, 4} (sum of 19) are not solutions to your previous state of {1, 6, 3, 2, 9} (sum of 21).
Related
So an example of the question is as follows:
Let's say we want to subdivide [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] into 3 sub-arrays.
While I imagine there are many correct answers one of them would be, [10, 8], [9, 7, 2], [1, 3, 4, 5, 6]. The reason being that here the sum of the sub arrays is, 18, 18, 19, meaning they are as close to equal as they can possibly be.
Is there an algorithm that can consistently return such an answer given any starting array and any number of sub-arrays to divide into? (Assuming that: length of the starting array > number of sub-arrays)
(PS If you want to show your logic in code I feel the most comfortable with python.)
Can anyone help me understand this coding problem assignment?
I have an array of numbers, where each number appears twice except for one, and I need to identify which is the number that only appears once.
E.g.
const num_list = [8, 6, 3, 2, 4, 2, 3, 4, 5, 8, 7, 7, 6]
Answer: 5
The thing I'm confused about though is the constraints given for the problem are:
2 <= num_list[i] <= 100000
3 <= i <= 10,000
In particular the second constraint given - What does 'i' refer to here? Is it just stating the minimum number of elements that will be in the array (there are multiple test cases with different arrays as input)? Or does it mean that if I iterate over the array I can only start iterating from index 3 of the array onwards?
Thanks in advance
You have N (N <= 50000) nodes on a line, with node i in position i on the line. You are given a sequence of M different swaps (M <= 20000), that is written in the from (a1, b1) (a2, b2) …. (aM, bM). In every unit of time i = 1…M, the nodes at positions ai and bi swap. Then, the same M swaps happen again in minutes M + 1….2M, and then for 2M + 1…3M, and so on, continuing a cyclic fashion for K units of time (K < 10^18).
So for example,
At unit of time 1, nodes at positions a1 and b1 swap.
At unit of time 2, nodes at positions a2 and b2 swap.
…
At unit of time M, nodes at positions aM and bM swap.
At unit of time M + 1, nodes at positions a1 and b1 swap.
At unit of time M + 2, nodes at positions a2 and b2 swap.
And so on…
For every node, you are asked to determine the number of unique positions that it will occupy.
Example:
6 nodes, M = 4 (sequence consists of 4 swaps), and K = 7 (total units of time is 7).
Sequence:
(1, 2) (2, 3) (3, 4) (4, 5)
Simulation:
Time 0: {1, 2, 3, 4, 5, 6}
Time 1: {2, 1, 3, 4, 5, 6}
Time 2: {2, 3, 1, 4, 5, 6}
Time 3: {2, 3, 4, 1, 5, 6}
Time 4: {2, 3, 4, 5, 1, 6}
Time 5: {3, 2, 4, 5, 1, 6}
Time 6: {3, 4, 2, 5, 1, 6}
Time 7: {3, 4, 5, 2, 1, 6}
Answer:
Node 1 reaches positions {1, 2, 3, 4, 5}, so 5 positions.
Node 2 reaches positions {1, 2, 3, 4}, so 4 positions.
Node 3 reaches positions {1, 2, 3}, so 3 positions.
Node 4 reaches positions {2, 3, 4}, so 3 positions.
Node 5 reaches positions {3, 4, 5}, so 3 positions.
Node 6 doesn’t move, so it reaches position {6}, so 1 position.
One way of solving this could be by treating the nodes as a graph. Then, you could treat each of the swaps as connections, and then use a graph algorithm to calculate how you move between the nodes.
How can I successfully incorporate a graph algorithm into this problem?
EDIT: I’ve spent a few more hours thinking about this problem, and wanted to incorporate Ehsan’s idea into the solution. To find the possible nodes that will be in each position, you can use a recursive function like the one Ehsan is proposing (F(F(...(F(original_order))). Then, you can do this for every step in K. However, this would be an NK solution, which my be too slow as the largest number of operations I can perform is 10^9. How can I optimize my current idea?
You doesn't need graph for this.
They key point is reducing k
Lemma: assume from original node list {n1,n2,n3,...,nN} after series of step {s1,s2,.....,st} you reach to new order of nodes like {n_i1,...,n_iN} and also you have a unique visited list for each node as {n1_v1,...,n1_vn1},...,{nN_v1,...,nN_vnN}
then if you perform the same series of steps again, you can find the new order list of nodes and also unique visited list in O(n) with help of previous step.
so it's kind of dynamic programing.
by this approach the complexity of your algorithm could be as O(n*log(k/m)+m)
I should have a complete array of numeric identifiers like this one:
a = [3, 4, 5, 6, 7, 8, 9, 10]
But instead, I have a a messed up array in random order, with duplicates and missing numbers like this one:
b = [4, 9, 7, 7, 3, 3]
Is there a more optimal way to find out which numbers are missing apart from substract the array without duplicates?
a - b.uniq
(a - b).empty?
works, but--depending on the data--it may not be the fastest way of determining if a contains an element not in b. For example, the probability were high that every element of a was not in b, it might be faster, on average, to check if a[0] is in b, then (if it is not) if a[1] is in b and so on, stopping if and when the element is in b. But again, that depends on the data, in particular the likelihood that (a - b).empty? is true. If that likelihood is great, Array#-, which is written in C, would be relatively fast and probably the best choice.
On the other hand, if its all but certain that a will contain many elements that is not in b it may be faster to do something like the following:
require 'set'
b_set = b.to_set
#=> #<Set: {4, 9, 7, 3}>
a.all? { |n| b_set.include?(n) }
In any event, you might first perform a cheap test:
b.size < a.size
If that is true there certainly will be at least one element of a that is not in b (assuming that a contains no duplicates).
Ruby 2.6 introduced Array#difference which seems perfect here:
a = [3, 4, 5, 6, 7, 8, 9, 10]
b = [4, 9, 7, 7, 3, 3]
a.difference(b)
# => [5, 6, 8, 10]
Seems handy for this, with the added benefit of being very readable.
I've got the following problem that I'm trying to find a more optimal solution for.
Let's say you have a range of numbers between 0 and 9:
Values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Now, let's say you "remove" 1, 4, 5, and 7:
Values: 0, -, 2, 3, -, -, 6, -, 8, 9
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Where there is no value, all subsequent values are shifted to the left:
Values: 0, 2, 3, 6, 8, 9
Index: 0, 1, 2, 3, 4, 5
The value at index 1 has now become 2 (was 1), the value at index 2 is now 3 (was 2), the value at index 3 is now 6 (was 3), etc.
Here's the problem. I need to manage this on a larger scale, up to tens of thousands of values. A random number of those values will be removed from the original contiguous range, and potentially added back afterwards (but not in the same order they were removed). The starting state will always be a complete sequence of numbers between 0 and MAX_VAL.
Things I've tried:
1) Maintaining an array of values, removing values from that array, and shifting everything over by one. This fails because you're iterating through all the values after the one you've just removed, and it's too slow as a result. Getting the value for a given index afterwards is really fast though.
2) Maintaining a linked list of values, and removing the value by pulling it out of the list. This seems to be slow both adding/removing values and getting the value at a given index, since I need to walk through the list first.
3) Keeping track of the "removed" values, rather then maintaining a giant array/list/etc of values from 0 to MAX_VAL. If the removed values are stored in an ordered array, then it becomes trivial to calculate how many values have been removed before and after a given index, and just return an offset index instead. This kinda works, except it's slow to maintain the ordered array of removed values and iterate through that instead, especially if the number of removed values approaches MAX_VAL.
Is there some sort of algorithm or technique that can handle this kind of problem more quickly and efficiently?
Is there some sort of algorithm or technique that can handle this kind of problem more quickly and efficiently?
The answer very much depends on typical use cases:
Is the set of numbers typically sparse or dense?
How often do you do insertions vs. removals vs. lookups?
In which patterns are numbers inserted or removed (random, continuous, from the end or start)?
What are there any memory constraints?
Here are some ideas for a generic solution:
Create a structure that stores ranges instead of numbers.
Start with a single entry: 0 - MAX_VAL.
A range can have subranges. This resulting graph of ranges forms a tree.
Removing a number splits a leaf range into two, creating two new leafs.
This algorithm would perform quite well when the set is dense (because there are few ranges). It would still perform somewhat fast when the graph grows (O(log n) for lookups) when you keep the tree balanced.
Now, let's say you "remove" 1, 4, 5, and 7:
Values: 0, -100, 2, 3, -100, -100, 6, -100, 8, 9// use a unique value that doesn't used in array
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9