30. Max Min Height

โœ… GFG solution to the Max Min Height problem: maximize minimum flower height after k days of watering using binary search and greedy strategy. ๐Ÿš€

The problem can be found at the following link: ๐Ÿ”— Question Link

๐Ÿงฉ Problem Description

Given a garden with n flowers planted in a row, represented by an array arr[] where arr[i] denotes the height of the ith flower. You will water them for k days. In one day you can water w continuous flowers. Whenever you water a flower its height increases by 1 unit. You have to maximize the minimum height of all flowers after k days of watering.

๐Ÿ“˜ Examples

Example 1

Input: arr[] = [2, 3, 4, 5, 1], k = 2, w = 2
Output: 2
Explanation: The minimum height after watering is 2.
Day 1: Water the last two flowers -> arr becomes [2, 3, 4, 6, 2]
Day 2: Water the last two flowers -> arr becomes [2, 3, 4, 7, 3]

Example 2

Input: arr[] = [5, 8], k = 5, w = 1
Output: 9
Explanation: The minimum height after watering is 9.
Day 1 - Day 4: Water the first flower -> arr becomes [9, 8]
Day 5: Water the second flower -> arr becomes [9, 9]

๐Ÿ”’ Constraints

  • $1 \le \text{arr.size()} \le 10^5$

  • $1 \le w \le \text{arr.size()}$

  • $1 \le k \le 10^5$

  • $1 \le \text{arr}[i] \le 10^9$

โœ… My Approach

The optimal approach uses Binary Search on Answer combined with a Greedy Watering Strategy:

Binary Search + Greedy Validation

  1. Binary Search Setup:

    • Search space: [min(arr), min(arr) + k]

    • For each candidate minimum height, check if it's achievable with k days

  2. Greedy Validation Strategy:

    • Use a sliding window approach to simulate watering effects

    • Track cumulative water added using a frequency array

    • When a flower's height is below target, greedily add water to achieve the target

    • Early termination if we exceed k days

  3. Sliding Window Optimization:

    • Maintain running sum of water effects within window w

    • Efficiently calculate current height by adding/removing window effects

    • Use prefix sum technique for optimal performance

  4. Maximize the Answer:

    • If current target is achievable, try a higher target

    • If not achievable, reduce the target

    • Return the maximum achievable minimum height

๐Ÿ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(n log k), where n is the array size and k is the number of days. Binary search takes O(log k) iterations, and each validation takes O(n) time to simulate the watering process.

  • Expected Auxiliary Space Complexity: O(n), as we use an auxiliary array to track the cumulative watering effects for each position in the garden.

๐Ÿง‘โ€๐Ÿ’ป Code (C++)

class Solution {
public:
    bool isPossible(vector<int> &arr, int k, int w, int maxHeight) {
        int n = arr.size();
        vector<int> water(n, 0);
        for (int i = 0; i < n; i++) {
            if (i > 0) water[i] = water[i - 1];
            int currHeight = arr[i] + water[i];
            if (i >= w) currHeight -= water[i - w];
            if (currHeight < maxHeight) {
                int add = maxHeight - currHeight;
                water[i] += add;
                k -= add;
                if (k < 0) return false;
            }
        }
        return true;
    }

    int maxMinHeight(vector<int> &arr, int k, int w) {
        int n = arr.size();
        int low = arr[0];
        for (int i = 1; i < n; i++) {
            if (arr[i] < low) low = arr[i];
        }
        int high = low + k, ans = low;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (isPossible(arr, k, w, mid)) {
                ans = max(ans, mid);
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return ans;
    }
};
โšก View Alternative Approaches with Code and Analysis

๐Ÿ“Š 2๏ธโƒฃ Optimized Space Approach with Sliding Window

๐Ÿ’ก Algorithm Steps:

  1. Use sliding window technique to track watering effects efficiently.

  2. Maintain running sum of water added within window.

  3. Apply binary search on answer with optimized space usage.

class Solution {
public:
    bool canAchieve(vector<int>& arr, int k, int w, int target) {
        int n = arr.size();
        vector<int> added(n, 0);
        int windowSum = 0;

        for (int i = 0; i < n; i++) {
            if (i >= w) windowSum -= added[i - w];

            int currentHeight = arr[i] + windowSum;
            if (currentHeight < target) {
                int need = target - currentHeight;
                added[i] = need;
                windowSum += need;
                k -= need;
                if (k < 0) return false;
            }
        }
        return true;
    }

    int maxMinHeight(vector<int>& arr, int k, int w) {
        int minVal = *min_element(arr.begin(), arr.end());
        int left = minVal, right = minVal + k, result = minVal;

        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (canAchieve(arr, k, w, mid)) {
                result = mid;
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return result;
    }
};

๐Ÿ“ Complexity Analysis:

  • Time: โฑ๏ธ O(n log k)

  • Auxiliary Space: ๐Ÿ’พ O(n) - For tracking water added

โœ… Why This Approach?

  • Uses STL min_element for cleaner code.

  • Optimized sliding window implementation.

  • Better variable naming for clarity.

๐Ÿ“Š 3๏ธโƒฃ Greedy with Prefix Sum Optimization

๐Ÿ’ก Algorithm Steps:

  1. Use prefix sum to efficiently calculate cumulative watering effects.

  2. Apply greedy strategy with early termination.

  3. Optimize binary search bounds.

class Solution {
public:
    bool solve(vector<int>& heights, int days, int range, int minHeight) {
        int n = heights.size();
        vector<long long> water(n + range, 0);
        long long used = 0;

        for (int i = 0; i < n; i++) {
            long long current = heights[i] + water[i];
            if (current < minHeight) {
                long long need = minHeight - current;
                used += need;
                if (used > days) return false;
                water[i] += need;
                if (i + range < n + range) water[i + range] -= need;
            }
            if (i + 1 < n + range) water[i + 1] += water[i];
        }
        return true;
    }

    int maxMinHeight(vector<int>& arr, int k, int w) {
        int low = *min_element(arr.begin(), arr.end());
        int high = low + k;
        int answer = low;

        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (solve(arr, k, w, mid)) {
                answer = mid;
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return answer;
    }
};

๐Ÿ“ Complexity Analysis:

  • Time: โฑ๏ธ O(n log k)

  • Auxiliary Space: ๐Ÿ’พ O(n + w)

โœ… Why This Approach?

  • Handles large numbers with long long.

  • Efficient prefix sum technique.

  • Optimized memory allocation.

๐Ÿ†š ๐Ÿ” Comparison of Approaches

๐Ÿš€ Approach

โฑ๏ธ Time Complexity

๐Ÿ’พ Space Complexity

โœ… Pros

โš ๏ธ Cons

๐Ÿ” Binary Search + Frequency Array

๐ŸŸข O(n log k)

๐ŸŸข O(n)

โšก Simple implementation

๐Ÿงฎ Multiple array operations

๐Ÿ”„ Sliding Window

๐ŸŸข O(n log k)

๐ŸŸข O(n)

๐Ÿ”ง Optimized window tracking

๐Ÿ’พ Similar space complexity

๐Ÿ”บ Prefix Sum

๐ŸŸข O(n log k)

๐ŸŸก O(n + w)

๐Ÿš€ Handles overflow, efficient

๐Ÿ’พ Extra space for range

๐Ÿ† Best Choice Recommendation

๐ŸŽฏ Scenario

๐ŸŽ–๏ธ Recommended Approach

๐Ÿ”ฅ Performance Rating

โšก Competitive programming, simple implementation

๐Ÿฅ‡ Binary Search + Frequency Array

โ˜…โ˜…โ˜…โ˜…โ˜…

๐Ÿ”ง Production code, optimized window operations

๐Ÿฅˆ Sliding Window

โ˜…โ˜…โ˜…โ˜…โ˜†

๐Ÿ“Š Large numbers, overflow concerns

๐Ÿฅ‰ Prefix Sum

โ˜…โ˜…โ˜…โ˜…โ˜†

๐Ÿง‘โ€๐Ÿ’ป Code (Java)

class Solution {
    boolean isPossible(int[] arr, int k, int w, int maxHeight) {
        int n = arr.length;
        int[] water = new int[n];
        for (int i = 0; i < n; i++) {
            if (i > 0) water[i] = water[i - 1];
            int currHeight = arr[i] + water[i];
            if (i >= w) currHeight -= water[i - w];
            if (currHeight < maxHeight) {
                int add = maxHeight - currHeight;
                water[i] += add;
                k -= add;
                if (k < 0) return false;
            }
        }
        return true;
    }

    public int maxMinHeight(int[] arr, int k, int w) {
        int n = arr.length;
        int low = arr[0];
        for (int i = 1; i < n; i++) {
            if (arr[i] < low) low = arr[i];
        }
        int high = low + k, ans = low;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (isPossible(arr, k, w, mid)) {
                ans = Math.max(ans, mid);
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return ans;
    }
}

๐Ÿ Code (Python)

class Solution:
    def isPossible(self, arr, k, w, maxHeight):
        n = len(arr)
        water = [0] * n
        for i in range(n):
            if i > 0:
                water[i] = water[i - 1]
            currHeight = arr[i] + water[i]
            if i >= w:
                currHeight -= water[i - w]
            if currHeight < maxHeight:
                add = maxHeight - currHeight
                water[i] += add
                k -= add
                if k < 0:
                    return False
        return True

    def maxMinHeight(self, arr, k, w):
        n = len(arr)
        low = min(arr)
        high = low + k
        ans = low
        while low <= high:
            mid = low + (high - low) // 2
            if self.isPossible(arr, k, w, mid):
                ans = max(ans, mid)
                low = mid + 1
            else:
                high = mid - 1
        return ans

๐Ÿง  Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: ๐Ÿ“ฌ Any Questions?. Let's make this learning journey more collaborative!

โญ If you find this helpful, please give this repository a star! โญ


๐Ÿ“Visitor Count

Visitor counter

Last updated