Start learning free

LESSON 459 OF 673 · HEAP

Minimum Number of Boats in Python (Time Complexity Analysis Included)

Practice O(n log n) Read the full explanation

You get a list weights. Each number is the weight of one student. You also get two limits, maxWeight and maxDiff.

All the students must cross a river by boat. There are as many boats as needed. Return the smallest number of boats that takes everyone across.

A boat carries one student or two. Two students can share a boat only if their weights add up to at most maxWeight. Their weights must also differ by at most maxDiff.

 

Example 1:

Input: weights = [3, 5, 4, 6], maxWeight = 9, maxDiff = 1
Output: 3
Explanation: One way is (3, 4), (5) and (6).
5 and 6 can't share a boat.
Together they weigh 11, more than 9.

Example 2:

Input: weights = [2, 9, 1, 8], maxWeight = 10, maxDiff = 3
Output: 3
Explanation: The boats are (1, 2), (8) and (9).
(1, 9) and (2, 8) are light enough.
But their weights differ by more than 3.

Example 3:

Input: weights = [12, 5, 4], maxWeight = 10, maxDiff = 2
Output: 2
Explanation: 4 and 5 share a boat.
The student who weighs 12 rides alone.

 

Constraints:

  • 1 to 30,000 students.
  • Each weight is from 0 to 100,000,000.
  • maxWeight is from 1 to 100,000.
  • maxDiff is from 1 to 10,000.
  • A student may weigh more than maxWeight. That student rides alone.
STEP 1 OF 14
    Ctrl + Enter to check

    PYTHON · HEAP

    Minimum Number Of Boats in Python, explained

    Understanding the Problem

    The core challenge of this problem is to minimize the number of boats required to transport all students given the constraints on weight and weight difference. This problem is significant in scenarios like evacuation planning, resource allocation, and load balancing.

    Potential pitfalls include not considering the weight difference constraint or not optimizing the pairing of students to minimize the number of boats.

    Approach

    To solve this problem, we can use a greedy algorithm. The idea is to sort the weights and try to pair the lightest and heaviest students that can share a boat. This approach ensures that we minimize the number of boats used.

    Initial naive solution might involve trying all possible pairs, but this would be computationally expensive. Instead, sorting the array and using a two-pointer technique is more efficient.

    Optimized Solution

    1. **Sort the weights array.**

    2. **Use two pointers:** one starting at the beginning (lightest) and one at the end (heaviest).

    3. **Try to pair the lightest and heaviest students:** If they can share a boat, move both pointers inward. If not, move only the pointer for the heaviest student.

    4. **Count the number of boats used.**

    Algorithm

    Here is a step-by-step breakdown of the algorithm:

    1. Sort the weights array.
    2. Initialize two pointers: `left` at the start and `right` at the end of the array.
    3. Initialize a counter for the number of boats.
    4. While `left` is less than or equal to `right`:
      • Check if the students at `left` and `right` can share a boat.
      • If they can, increment `left` and decrement `right`.
      • If they cannot, decrement `right` only.
      • Increment the boat counter.
    5. Return the boat counter.

    Code Implementation

    def min_boats(weights, maxWeight, maxDiff):
        # Sort the weights array
        weights.sort()
        
        # Initialize two pointers
        left, right = 0, len(weights) - 1
        boats = 0
        
        # Use two-pointer technique to find the minimum number of boats
        while left <= right:
            # If the lightest and heaviest can share a boat
            if weights[left] + weights[right] <= maxWeight and abs(weights[left] - weights[right]) <= maxDiff:
                left += 1  # Move the left pointer inward
            # Move the right pointer inward in both cases
            right -= 1
            # Increment the boat counter
            boats += 1
        
        return boats
    
    # Example usage
    print(min_boats([2, 4, 2, 1], 6, 1))  # Output: 3
    print(min_boats([81, 37, 32, 88, 55, 93, 45, 72], 100, 10))  # Output: 6
    

    Complexity Analysis

    The time complexity of this approach is O(n log n) due to the sorting step. The space complexity is O(1) as we are using only a few extra variables.

    Compared to a naive O(n^2) approach, this is significantly more efficient.

    Edge Cases

    Potential edge cases include:

    • All students having the same weight.
    • Weights such that no two students can share a boat.
    • Empty weights array.

    These cases are handled by the algorithm as it inherently checks the constraints and processes the array accordingly.

    Testing

    To test the solution comprehensively, consider:

    • Simple cases with a few students.
    • Cases with maximum constraints.
    • Edge cases as mentioned above.

    Using a testing framework like `unittest` in Python can help automate and validate these tests.

    Thinking and Problem-Solving Tips

    When approaching such problems:

    • Break down the problem into smaller parts.
    • Consider edge cases and constraints early.
    • Think about different approaches and their trade-offs.
    • Practice similar problems to improve problem-solving skills.

    Conclusion

    Understanding and solving this problem helps in developing skills in greedy algorithms and two-pointer techniques. These are widely applicable in optimization problems.

    Practice and exploration of similar problems can further enhance your problem-solving abilities.

    Additional Resources

    For further reading and practice:

    Keep going with Python650+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free