算法修炼|503.下一个更大元素II ● 42. 接雨水

52 阅读2分钟

LeetCode:503. 下一个更大元素 II - 力扣(LeetCode)

1.思路

方法一:暴力求解:两层for循环,外层遍历定位当前位置,内层遍历比较找出外层位置之后第一个较大值nums[j](这个过程循环遍历,因此用到取模操作,同时考虑不存在大于nums[i]的值,做个标记位用于结束循环)。当存在nums[j]>nums[i]时,则有ans[i] = nums[j];break;即可。 方法二:单调栈法:

2.代码实现
// 暴力解法
class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] ans = new int[nums.length];
        Arrays.fill(ans, -1);
        for (int i = 0; i < nums.length; i++) {
            // 循环判断?
            int flag = 0;
            for (int j = (i + 1) % nums.length; j >= 0; j = (j + 1) % nums.length) {
                flag++;
                if (flag > nums.length) {
                    break;
                }
                if (nums[j] > nums[i]) {
                    ans[i] = nums[j];
                    break;
                }
            }
        }
        return ans;
    }
}
// 单调栈法
class Solution {
    public int[] nextGreaterElements(int[] nums) {
        // 下一个更大元素,则需要维持单调栈是单调递增的
        int[] ans = new int[nums.length];
        Arrays.fill(ans, -1);
        Stack<Integer> stack = new Stack<>();
        // 保证每个元素比较,需要循环遍历至少一圈
        for (int i = 0; i < 2 * nums.length; i++) {
            while (!stack.isEmpty() && nums[i % nums.length] > nums[stack.peek()]) {
                ans[stack.peek()] = nums[i % nums.length];
                stack.pop();
            }
            stack.push(i % nums.length);
        }
        return ans;
    }
}
3.复杂度分析

时间复杂度:O(n ^ 2).

空间复杂度:O(n).

LeetCode:42. 接雨水 - 力扣(LeetCode)

1.思路

方法一:暴力解法,似乎也是双指针法。索引下垂直求解。以当前节点为中心,分别向两侧寻找两侧最高的柱子,木桶原理获取两者较小值与当前柱子高度的差,如果差大于0,sum+=diff。循环进行,返回结果。

方法二:单调栈法。索引下水平求解。当nums[i]<=nums[stack.peek()],直接入栈。当nums[i] >nums[stack.peek()] && !stack.isEmpty(),循环判断计算。标记栈顶mid=stack.pop(),此时的i和stack.peek()为mid的右和左的第一个较大值,高度差为diff = Math.min(nums[i],nums[stack.peek()]) - nums[i].(这个过程用到stack.peek(),因此需要判空).if(diff > 0) sum += diff * (i - stack.peek() - 1),结束while,将i加入栈。返回结果。

2.代码实现
// 暴力解法:
class Solution {
    public int trap(int[] height) {
        int sum = 0;
        for (int i = 0; i < height.length; i++) {
            if (i == 0 || i == height.length - 1) {
                continue;
            }
            int rHeight = height[i];
            int lHeight = height[i];
            // 向右寻找最高的柱子
            for (int j = i + 1; j < height.length; j++) {
                if (height[j] > rHeight) {
                    rHeight = height[j];
                }
            }
            // 向左寻找最高的柱子
            for (int k = i - 1; k >= 0; k--) {
                if (height[k] > lHeight) {
                    lHeight = height[k];
                }
            }
            // 左右两个柱子较小的高度决定能装的雨水
            int h = Math.min(lHeight, rHeight) - height[i];
            if (h > 0) {
                sum += h;
            }
        }
        return sum;
    }
}
// 单调栈
class Solution {
    public int trap(int[] height) {
        int sum = 0;
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        for (int i = 1; i < height.length; i++) {
            if (height[i] <= height[stack.peek()]) {
                stack.push(i);
            } else if (height[i] > height[stack.peek()]){
                while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
                    int mid = stack.pop();
                    if (!stack.isEmpty()) {
                        int diff = Math.min(height[i], height[stack.peek()]) - height[mid];
                        if (diff > 0) {
                            sum += diff * (i - stack.peek() - 1);
                        }
                    }
                }
                stack.push(i);
            }
        }
        return sum;
    }
}
3.复杂度分析

时间复杂度:O(n^2).

空间复杂度:O(n).