LeetCode Entry

962. Maximum Width Ramp

10.10.2024 medium 2024 kotlin rust

Max j-i between a[i] <= a[j] in an array stack

962. Maximum Width Ramp medium blog post substack youtube 1.webp

Join me on Telegram

https://t.me/leetcode_daily_unstoppable/764

Problem TLDR

Max j-i between a[i] <= a[j] in an array #medium #monotonic_stack #sorting

Intuition

The simple monotonic stack will not solve this: we should not drop the values on any increase/decrease.

Let’s think what else we can do, sort, for example:


    // 3 7 2 4 9 6 8 1 0 5
    // 0 0 1 1 1 4 4 8 9 9
    // * *                 (3, 7) min = 3, max = 7
    //     * * *           (2, 4, 9) min = 2, max = 9
    //           * *       (6, 8) + (2), min=2, max = 9
    //               *     min=2, max=9
    //                 * * min=2, max=9

On the sorted order we can track a min and max index, and reset the max when a new min happens. This solution is accepted and it is O(nlog(n))

However, there is a monotonic stack solution that exists. This stack should be the j indices in a strictly decreasing order and as right as possible.

Approach

  • try several ways to transform the data, sorting, monotonic stacks, see what is helpful for the problem

Complexity

  • Time complexity: \(O(n)\) or O(nlogn)

  • Space complexity: \(O(n)\)

Code


    fun maxWidthRamp(nums: IntArray): Int {
        val inds = nums.indices.sortedBy { nums[it] }
        var min = nums.size; var max = -1
        return inds.maxOf { i ->
            max = if (i < min) i else max(max, i)
            min = min(min, i)
            max - min
        }
    }


    pub fn max_width_ramp(nums: Vec<i32>) -> i32 {
        let (mut stack, mut res) = (vec![], 0);
        stack.push(nums.len() - 1);
        for (i, &n) in nums.iter().enumerate().rev() {
            if n > nums[*stack.last().unwrap()] { stack.push(i) }}
        for (i, &n) in nums.iter().enumerate() {
            while stack.len() > 0 && n <= nums[*stack.last().unwrap()] {
                res = res.max(stack.pop().unwrap() - i) }}
        res as i32
    }


    int maxWidthRamp(vector<int>& n) {
        vector<int> s; int res = 0;
        for (int i = n.size() - 1; i >= 0; --i)
            if (s.empty() || n[i] > n[s.back()]) s.push_back(i);
        for (int i = 0; i < n.size() && !s.empty(); ++i)
            while (!s.empty() && n[i] <= n[s.back()])
                res = max(res, s.back() - i), s.pop_back();
        return res;
    }