Equal elements in a Array - java

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.

Related

What exactly does array of size N mean?

Sorry if this may be a stupid question, but in my Java book I read this sentence:
Thus, when iterating over an array of size N, the enhanced for obtains
the elements in the array in index order, from 0 to N-1.
I am reading about the for-each style for loop, and suddenly the book is talking about an array of size N and an index order of 0 to N-1. The book does not explain what N means, and strangely enough I googled a lot but could not find the answer. Maybe I am thinking to literally or too difficult. What does size N mean? Can someone give more information about this?
The size N (or whatever it is named) is the number of items in your array or collection. Since indices are zero-based (as in other languages like C, Python, OCaml, ...), they run from 0 to N – 1.
As an example, if you have a 20-item array, N = 20 and the valid indices for this array run from 0 to 19.
An array is basically a fixed size list of elements. Here N refers to the size (or length) of the array. So it's the number of elements that it can store.
Elements in an array are obtained by using a zero-based index. That means the first element is at index 0, the second at index 1, and so on. Therefore, if the array has size N, the last element will be at index N-1 (because it starts with 0). Thus the index is in the interval [0, N-1].
Here is the official doc for arrays explaining the basics in detail.
Java provides a data structure, the array, which stores a fixed-size
sequential collection of elements of the same type. An array is used
to store a collection of data, but it is often more useful to think of
an array as a collection of variables of the same type.
N is the number of items that you can store in your array.
See this link for more information:
http://www.tutorialspoint.com/java/java_arrays.htm
Hi Simon when an array has size N means that has no defined dimension that can be 1 to N.
When you don't know exactly wich is the size then in "math language" you just say N size. Be careful anyway that in Java an array can be initialized with size 0
Example:
Integer[] array = new Integer[];
Creates an empty array with length = 0.
I suggest you to have a look not only at your book but also at the official java tutorials in order to have practical code examples
N come from Natural number https://en.wikipedia.org/wiki/Natural_number but in java think of it as an int >= 0
Array size of N means the size of that array is N. It is like saying...that container holds 5 gallons or 10 gallons etc. So for a array size of 5, N=5 and for a array size of 9, N=9 and so on.
If N=9, we can store 9 elements in that array and we will access these 9 elements starting from the index 0 all the way up to index 8. Remember that there is no 9th index here because we are starting from the 0th index and when we reach index 8, we will be accessing the 9th element.
This may seem a bit tough to digest for you at this stage of your programming career....you will become comfortable after a few months, after you have seen this a few more times.
N is just a variable, it represents the amount of items could be in the array. The array could be 5 items, it could be 10 items, it could be 1000 items, it could be N items. Arrays begin from index 0, so the loop would run 0, 1, 2, 3 ... N - 3, N - 2, N - 1 times.
For example, an array with 5 elements means N = 5.

Generating a partially ordered random list of numbers

I want to generate a list of random numbers of size 500, where the list is exactly 30% sorted (I know how to generate a list of at least 30% sorted), but that's not what i want, how do i generate a file that is "exactly" 30%? I'm stuck, How can this be done?
Here is the exact wording
"For the sorts, you should construct three different files of each size: ordered, keys in reverse order, and finally one in which 30% of the keys are ordered. The latter file should not consist of files in which your sort is 30% complete, but rather in files in which 30% of the keys are correctly placed with respect to one another but are not necessarily contiguous.
There are 2 main ideas I can see for percentage sorted:
Simply the number of elements out of place.
Once should be able to get an estimated % sorted by sorting it, then iterating through it, and, keeping each element the same with the desired percentage as probability, otherwise swapping it with a random remaining element (so, if we want 30% sorted, we'll keep an element the same with 30% probability, and swap it with 70%).
If an exact number is needed, one could use the above result and (intelligently) swap random elements until the desired percentage is obtained.
The number of inversions.
An inversion is a pair of places of a sequence where the elements on these places are out of their natural order.
One idea is to first sort it, then to swap random elements that get us closer to the desired percentage sorted, until we get there.
Only swapping elements that get us closer to the desired result is difficult (at least doing so efficiently).
A very brute force approach would be to count the change in the number of inversions that each pair of swaps would cause, and then pick a random one that gets us closer to our target.
Another idea is to just generate random pairs and count the number of inversions until we find one that gets us closer.
A third option is to pick a random element. If it's larger than half the elements, try to move it left (ideally increasing the number of inversions). If it's smaller, try to move it right. In trying to move it left/right, we can look for a smaller / larger element (respectively) to swap it with and count the change in inversions (we only need to consider the elements between the swapped elements when counting the change in inversions).
At first we could probably just randomly swap elements as we're likely to tend to more inversions.
If the percentage is above 50%, we could also start with a reversed array, i.e. 100% unsorted.
There's a one-to-one correspondence that maps permutations to {0} x {0, 1} x {0, 1, 2} x ... x {0, 1, ... n - 1}, where the jth element of the tuple in the codomain is the number of inversions involving elements at positions j and i < j. In this light, the problem is sampling a random element of the codomain that sums to the desired number of inversions.
Here's an instance of Gibbs sampling for this problem. Initialize a tuple summing to the desired number of permutations. Repeatedly select two distinct indices and randomize uniformly among all possibilities with the same sum. Stop when you're tired of waiting (the distribution converges on uniform but never gets there; maybe tomorrow I will figure out a Propp--Wilson style technique for exact samples).
In Python (untested):
import random
def gibbs(n, target):
perm = [0] * n
for i in range(n):
perm[i] = min(target, i)
target -= i
assert target == 0
while ???:
i = random.randrange(n)
j = random.randrange(n)
if i == j: continue
total = perm[i] + perm[j]
perm[i] = random.randrange(max(total - j, 0), i + 1)
perm[j] = total - perm[i]
for j in range(n):
perm[j] = j - perm[j]
for i in range(j):
if perm[i] >= perm[j]: perm[i] += 1
return perm
One could also get exact samples by dynamic programming and conditional probability, but the running time for 500 looks slightly prohibitive from here.

Smallest range that includes at least one number from each of the k lists

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.

generate random order but with constraint in java

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.

custom partition problem

Could some one guide me on how to solve this problem.
We are given a set S with k number of elements in it.
Now we have to divide the set S into x subsets such that the difference in number of elements in each subset is not more than 1 and the sum of each subset should be as close to each other as possible.
Example 1:
{10, 20, 90, 200, 100} has to be divided into 2 subsets
Solution:{10,200}{20,90,100}
sum is 210 and 210
Example 2:
{1, 1, 2, 1, 1, 1, 1, 1, 1, 6}
Solution:{1,1,1,1,6}{1,2,1,1,1}
Sum is 10 and 6.
I see a possible solution in two stages.
Stage One
Start by selecting the number of subsets, N.
Sort the original set, S, if possible.
Distribute the largest N numbers from S into subsets 1 to N in order.
Distribute the next N largest numbers from S the subsets in reverse order, N to 1.
Repeat until all numbers are distributed.
If you can't sort S, then distribute each number from S into the subset (or one of the subsets) with the least entries and the smallest total.
You should now have N subsets all sized within 1 of each other and with very roughly similar totals.
Stage Two
Now try to refine the approximate solution you have.
Pick the largest total subset, L, and the smallest total subset, M. Pick a number in L that is smaller than a number in M but not by so much as to increase the absolute difference between the two subsets. Swap the two numbers. Repeat. Not all pairs of subsets will have swappable numbers. Each swap keeps the subsets the same size.
If you have a lot of time you can do a thorough search; if not then just try to pick off a few obvious cases. I would say don't swap numbers if there is no decrease in difference; otherwise you might get an infinite loop.
You could interleave the stages once there are at least two members in some subsets.
There is no easy algorithm for this problem.
Check out the partition problem also known as the easiest hard problem , that solve this for 2 sets. This problem is NP-Complete, and you should be able to find all the algorithms to solve it on the web
I know your problem is a bit different since you can chose the number of sets, but you can inspire yourself from solutions to the previous one.
For example :
You can transform this into a serie of linear programs, let k be the number of element in your set.
{a1 ... ak} is your set
For i = 2 to k:
try to solve the following program:
xjl = 1 if element j of set is in set number l (l <= i) and 0 otherwise
minimise max(Abs(sum(apxpn) -sum(apxpm)) for all m,n) // you minimise the max of the difference between 2 sets.
s.t
sum(xpn) on n = 1
(sum(xkn) on k)-(sum(xkm) on k) <= 1 for all m n // the number of element in 2 list are different at most of one element.
xpn in {0,1}
if you find a min less than one then stop
otherwise continue
end for
Hope my notations are clear.
The complexity of this program is exponential, and if you find a polynomial way to solve this you would probe P=NP so I don't think you can do better.
EDIT
I saw you comment ,I missunderstood the constraint on the size of the subsets (I thought it was the difference between 2 sets)
I don't I have time to update it I will do it when I have time.
sryy
EDIT 2
I edited the linear program and it should do what it's asked to do. I just added a constraint.
Hope this time the problem is fully understood, even though this solution might not be optimal
I'm no scientist, so I'd try two approaches:
After sorting items, then going from both "ends" and moving first and last to the actual set,then shift to next set, loop;
Then:
Checking the differences of sums of the sets, and shuffling items if it would help.
Coding the resulting sets appropriately and trying genetic algorithms.

Categories

Resources