Suppose you have N objects distributed unevenly in N containers. You can move one object from a container to an adjacent container, it is considered to be one move. What is the strategy that minimizes the number of moves to keep the time complexity O(N)?
Example 1. Suppose you have 5 containers that are filled as:
1, 2, 1, 1, 0
You will need three moves to pass one object from the second container to the last one ->, move from 2nd to the third first, then to the fourth and finally to the fifth:
1, 1, 2, 1, 0
1, 1, 1, 2, 0
1, 1, 1, 1, 1
Example 2. Now a bit more complicated one.
Suppose you have 5 containers and all objects are in the last container:
0, 0, 0, 0, 5
Obviously, you will move from right to the left:
0, 0, 0, 1, 4
0, 0, 1, 0, 4
0, 1, 0, 0, 4
1, 0, 0, 0, 4
1, 0, 0, 1, 3
1, 0, 1, 0, 3
1, 1, 0, 0, 3
1, 1, 0, 1, 2
1, 1, 1, 0, 2
1, 1, 1, 1, 1
It takes 10 moves
Example 3. All objects are in the middle:
0, 0, 5, 0, 0
That is what seems right:
0, 1, 4, 0, 0
1, 0, 4, 0, 0
1, 1, 3, 0, 0
1, 1, 2, 1, 0
1, 1, 2, 0, 1
1, 1, 1, 1, 1
It takes 6 moves
The problem weakly reminds a so-called pigeonhole or Dirichlet principle – that n item are put into m containers, with n>m, then at least one container must contain more than one item. Hence it appears in the title.
Approach sounds rather trivial: move along the row of containers from the beginning to the end, if you meet an empty container, fill it, and if you meet a container with several objects (more than one), try to decrease the amount to just one.
More precisely, one must keep a queue of containers with too many objects and another queue of empty places and use them to pass objects. Obviously, since we try to pass objects as soon as there is a possibility, one of the queues will become empty on every step after we make all possible movements.
Still more detailed:
Every time we meet an empty place, we check if there is something in the queue of containers with multiple objects, if yes, take one object and fill the empty place. If no, add this empty place to the queue.
Every time we meet an overcrowded container, check if the queue of empty spaces has something, if yes, try to put objects from the current container as many as possible into these empty containers and remove them from their queue. If no empty ready, push the overcrowded container into the queue for full containers.
The queue for overcrowded containers keeps pairs of numbers: location and amount of superfluous objects. The queue for empty containers keeps just numbers for locations since they are empty.
If the input is supplied as an array of coordinates of objects A, first reorganize it like an array of amounts per location.
This problem can be in more then one dimensions like in the Codility challenge Selenium 2016, which inspired this article. But since dimensions are independent, the results min every dimension just summarized to get the final answer.
The full implementation for the problem in Codility includes that the final answer is taken Modulo 10^9+7.
Input : Coordinates of objects are X = [1, 2, 2, 3, 4] and array Y = [1, 1, 4, 5, 4] Output : 5 Input : X = [1, 1, 1, 1] and array Y = [1, 2, 3, 4] Output : 6 Input : X = [1, 1, 2] and array Y = [1, 2, 1] Output : 4
Note: there is another way to do it, possibly will be covered in another article, inspired by a more hard problem in Codility Future Mobility Challenge. It includes the following steps:
- Subtract from every location 1, now we strife for all 0 instead of all 1
- Cut the array into fragments such as in every fragment the movement of objects are all in one direction, starting and trailing zeroes can be dropped for evey fragment. Sample: 1, 0, -1, 0, -2, 2 is cut into 1, 0, -1 and -2, 2. The cut points are discovered by zeroes of prefix sum
- For every fragment calculate the second integral. That is the prefix of prefix from left to right. The most right value is the amount of moves. Sample sequence: 1, 0, -1. The prefix is 1, 1, 0. The second prefix is 1, 2, 2. The answer for this fragment is 2 (two moves from 0 to 2)
- The result is the sum of results for all fragments
The final implementation of the first way:
Result: 5 Result: 6 Result: 4 Result: 54 Result: 54 Result: 3 Result: 3 Result: 4 Result: 4 Result: 8 Result: 8 Result: 192 Result: 192
- Extract unique objects by attribute from array of objects.
- Count number of 1s in the array after N moves
- Collect maximum points in an array with k moves
- Print direction of moves such that you stay within the [-k, +k] boundary
- Array element moved by k using single moves
- Minimum number of moves after which there exists a 3X3 coloured square
- Find the index of the left pointer after possible moves in the array
- Minimum number of moves to make all elements equal
- Find the minimum number of moves to reach end of the array
- Minimum moves required to change position with the given operation
- Minimum number of moves to make a binary array K periodic
- Print all paths from top left to bottom right in a matrix with four moves allowed
- Expected number of moves to reach the end of a board | Matrix Exponentiation
- Find maximum path sum in a 2D matrix when exactly two left moves are allowed
- Count minimum number of "move-to-front" moves to sort an array
If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to firstname.lastname@example.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.