Start learning free

LESSON 252 OF 410 · TWO POINTERS

Container with Most Water - JavaScript Solution and Time Complexity Analysis /homework

Practice O(n) Read the full explanation

You are given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i are (i, ai) and (i, 0). Find two lines, which together with the x-axis form a container, such that this container contains the most water.

Note: You may not slant the container and n is at least 2.

 

The above vertical lines are represented by the array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) one container can contain is 49.

 

Example:

Input: [1,8,6,2,5,4,8,3,7]
Output: 49
STEP 1 OF 7
    Ctrl + Enter to check

    JAVASCRIPT · TWO POINTERS

    Container With Most Water in JavaScript, explained

    Understanding the Problem

    The core challenge of this problem is to find two lines that, together with the x-axis, form a container that can hold the maximum amount of water. The height of the water is determined by the shorter of the two lines, and the width is the distance between the two lines.

    This problem is significant in various fields such as computer graphics, fluid dynamics, and optimization problems. A common pitfall is to assume that the tallest lines will always form the container with the most water, which is not necessarily true.

    Approach

    To solve this problem, we can start with a naive approach and then move to a more optimized solution.

    Naive Solution

    The naive solution involves checking all possible pairs of lines and calculating the area for each pair. This approach has a time complexity of O(n^2), which is not efficient for large inputs.

    Optimized Solution

    A more efficient approach is to use the two-pointer technique. We start with two pointers, one at the beginning and one at the end of the array. We calculate the area formed by the lines at these two pointers and then move the pointer pointing to the shorter line inward. This process is repeated until the two pointers meet.

    This approach has a time complexity of O(n), which is much more efficient.

    Algorithm

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

    1. Initialize two pointers, one at the beginning (left) and one at the end (right) of the array.
    2. Initialize a variable to keep track of the maximum area found.
    3. While the left pointer is less than the right pointer:
      • Calculate the area formed by the lines at the left and right pointers.
      • Update the maximum area if the calculated area is greater.
      • Move the pointer pointing to the shorter line inward.
    4. Return the maximum area found.

    Code Implementation

    /**
     * @param {number[]} height
     * @return {number}
     */
    var maxArea = function(height) {
        // Initialize two pointers
        let left = 0;
        let right = height.length - 1;
        // Variable to store the maximum area
        let maxArea = 0;
        
        // Loop until the two pointers meet
        while (left < right) {
            // Calculate the area
            const width = right - left;
            const currentHeight = Math.min(height[left], height[right]);
            const area = width * currentHeight;
            
            // Update the maximum area if the current area is greater
            maxArea = Math.max(maxArea, area);
            
            // Move the pointer pointing to the shorter line inward
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        
        // Return the maximum area found
        return maxArea;
    };

    Complexity Analysis

    The time complexity of the optimized solution is O(n) because we only traverse the array once with the two pointers. The space complexity is O(1) as we are using a constant amount of extra space.

    Edge Cases

    Some potential edge cases include:

    • All elements in the array are the same.
    • The array has only two elements.
    • The array contains very large numbers.

    Each of these cases is handled by the algorithm without any special modifications.

    Testing

    To test the solution comprehensively, we should include a variety of test cases:

    console.log(maxArea([1,8,6,2,5,4,8,3,7])); // Output: 49
    console.log(maxArea([1,1])); // Output: 1
    console.log(maxArea([4,3,2,1,4])); // Output: 16
    console.log(maxArea([1,2,1])); // Output: 2

    Thinking and Problem-Solving Tips

    When approaching such problems, it's essential to:

    • Understand the problem requirements and constraints thoroughly.
    • Start with a brute-force solution to get a feel for the problem.
    • Look for patterns and optimizations to improve the solution.
    • Practice similar problems to develop problem-solving skills.

    Conclusion

    In this blog post, we discussed the "Container with Most Water" problem, explored a naive solution, and then optimized it using the two-pointer technique. We also analyzed the complexity and tested the solution with various test cases. Understanding and solving such problems is crucial for improving algorithmic thinking and coding skills.

    Additional Resources

    For further reading and practice, consider the following resources:

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