Python Solution of Aggressive Cows Problem

In this problem, we will be given a sorted array of integers. Let the size of this array be N. The integer N represents the position of a stall. We will be given another integer, K, which represents the number of cows we have to arrange. Our task in this problem is to assign the given stalls in the array to K number of cows such that the minimum distance between any two cows is the maximum possible distance.

Let us see some examples to understand the problem

Examples:

Input: N = 6, K = 4, array = [1, 3, 6, 9, 10, 13]

Output: 3

Explanation: We can place cow 1 at position 1, cow 2 at position 4, and cow 3 at position 9. So, the maximum possible minimum distance between two cows is 3.

Input: N = 7, K = 3, array = [5, 7, 10, 13, 16, 19, 21]

Output: 2

Explanation: We can place cow 1 at position 6, cow 2 at position 9, and cow 4 at position 15. So, the maximum possible minimum distance between two cows is 2.

Approach - 1

This is a brute-force approach. In this approach, we will first find the maximum distance possible between two cows in the given array of stall locations. This distance is the difference between the stall at the farthest location and the stall at the nearest location. In terms of array, this is the difference between the maximum and minimum elements of the array.

Since integers mark stall locations, the minimum distance between any two stalls can be only 1.

Let us first dry-run the code.

  • Input: N = 6, K = 4, arr = [1, 3, 6, 9, 10, 13].
  • The maximum element of the given array, i.e., the farthest stall, is 13. Therefore, we will run a for loop in the range 1 to 13.
  • At the first iteration, i = 1, we can assign 1, 3, 6, and 9 stalls to the cows. The minimum distance between the stalls is 2.
  • In the second iteration, we can assign 1, 6, 9, 10. In this manner, the minimum distance is 1.
  • In the third iteration, we can assign 1, 9, 10 13. In this manner, the minimum distance is 1.
  • In the fourth iteration, we can assign 3, 6, 9, 10. In this manner, the minimum distance is 1.

Here is the Python code of the above approach.

Code

Output

3

Time Complexity: We are running a nested loop in this problem. The outer loop will run till the maximum element of the array. Hence, the time complexity will be O(N * (max(given array))

Auxiliary Space: We have not used any extra space; therefore, the space complexity is constant. O(1).

Approach - 2

There is a much better approach than brute force. This efficient approach will use a Binary Search algorithm.

In the brute force approach, we have iterated from 1 to the maximum element of the array. For every element of the iteration, we will check if that particular distance can be our possible answer. We can optimize the iteration process by using binary search on the same range, i.e., from 1 to the maximum element of the array.

We will follow the following steps to solve this problem:

  • We aim to find the arrangement of k cows in n stalls such that the minimum distance between two cows is maximum.
  • We have to iterate over the range 1 to the maximum element of the array, assuming that the distance of each iteration is the minimum distance between two cows and the maximum solution.
  • We will apply binary search on this range.
  • In each iteration, we will calculate the middle value and check if the middle value can be answered.
    • We will use the same method as we used in the above approach to check if the middle value is the solution or not.
    • If the middle value is the answer, then we will check on the right side because we have to find the maximum of all possible solutions.
    • Otherwise, we will move to the left side of the range.
  • When the binary search is completed, we will be left with the final answer.

Let us understand this approach using an example.

Input: N = 6, K = 4, arr = [1, 3, 6, 9, 10, 13].

The maximum element of the array is 13. Therefore, the range in which we have to search for the answer is 1 to 13.

Initially l = 1, h = 13

In the first iteration, we will find the middle element, which will be (1 + 13) // 2 = 7. We can see we cannot place all the cows in the stall with a minimum distance equal to 7. Therefore, we will move to the left side of the range. Now h = mid - 1 = 6

In the second iteration mid = (1 + 6) // 2 = 3. We will see that we can place cows in the given stalls with a minimum distance equal to 3. Now, we have to find the optimal solution, which is the maximum distance of all the possible solutions. Therefore, we will move the store this distance and move towards the right. Now, l = mid + 1 = 4.

In the third iteration mid = (6 + 4) // 2 = 5. We can see that 5 cannot be the answer. Hence, now we have to move towards the left side to find the answer. Therefore, the updated value of h is mid - 1, i.e., 4.

In this last iteration, l = h = 4. Therefore, the mid value is also equal to 4. We can see that 4 cannot be the minimum distance in order to arrange the cows in the given stall. So now we will move to the left side. The updated value of h = mid - 1 = 3.

Since l > h, the while loop is completed, and the final answer is the one that we stored in the second iteration, i.e., 3.

Here is the Python code for this approach

Code

Output

3

Time Complexity: We are using a single binary search execution, but in each iteration, we are using a linear program to check if that particular iteration gives us an answer or not. Therefore, the time complexity is N times log(N), i.e., O(N * log(max(array)))

Auxiliary Space: We have not used any extra space; therefore, the space complexity is O(1).

Approach - 3

Let us first revise our approaches and track the thought process through which we will reach the most efficient approach.

In the brute force solution, we iterate over a range starting from 0 to the maximum element of the array. We knew that the answer could be in this range only since the minimum distance between two stalls is 1, and the maximum element forms the upper bound on this distance.

Then, rather than linearly iterating over this range, we used Binary Search to optimize the search, which decreased the time from O(N^2) to O(N * Log N).

In this approach, we will further optimize the solution by modifying this range. In the given array, the maximum possible distance between any two stalls can be the difference between the maximum element and the minimum element of the array. Also, the minimum distance between any two stalls has to be 1. Thus, we will execute a binary search from 1 to max_element - min_element rather than 0 to max_element.

Our array of stalls is a sorted array. Therefore, instead of using max and min functions, we can use indexing as the maximum element = array[-1] and minimum element = array[0]. So, the maximum possible distance = array[-1] - array[0].

It does not create any difference; however, when the array size is very large, this method will eliminate a lot of iterations.

Suppose an array of length 1000. Where a minimum element is 500, and the maximum element is 1000, array = [500,….1000] N = 1000, K = 3

In the normal binary search, the search range will be from 0 to 1000.

In the current approach, the search range will be from 1 to (1000 - 500) = 500, which is half of the previous search range.

Here is the Python code for the above approach.

Code

Output

3

Time Complexity: The time complexity has the same pattern as that of binary search. Log M for binary search and N for the linear function to check if the cows can be arranged or not. Therefore, O(N * log M), here

N = Length of the array.

M = array[-1] - array[0] (last/max element - first/min element)

Auxiliary Space: We have not used any extra space; therefore, the space complexity is constant, i.e., O(1)