接雨水(栈、数组)

n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:

  • n == height.length
  • 0 <= n <= 3 * 104
  • 0 <= height[i] <= 105

以下程序实现了这一功能,请你填补空白处内容:

class Solution {
	public int trap(int[] height) {
		if (height == null)
			return 0;
		int len = height.length;
		if (len == 0)
			return 0;
		int res = 0;
		int[] left_max = new int[len];
		int[] right_max = new int[len];
		left_max[0] = height[0];

		for (int i = 1; i < len; i++) {
			left_max[i] = Math.max(height[i], left_max[i - 1]);
		}
		right_max[len - 1] = height[len - 1];

		____________________;

		for (int i = 1; i < len - 1; i++) {
			res += Math.min(left_max[i], right_max[i]) - height[i];
		}
		return res;
	}
}

解答:

for (int i = len - 2; i >= 0; i--) {
	right_max[i] = Math.max(height[i], right_max[i + 1]);
}

俄罗斯套娃信封问题(数组、二分查找)

给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。 当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。 请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。 注意:不允许旋转信封。 示例 1: 输入:envelopes = [[5,4],[6,4],[6,7],[2,3]] 输出:3 解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。 示例 2: 输入:envelopes = [[1,1],[1,1],[1,1]] 输出:1

提示:

  • 1 <= envelopes.length <= 5000
  • envelopes[i].length == 2
  • 1 <= wi, hi <= 104

解答:

class Solution {
    public int maxEnvelopes(int[][] envelopes) {
        int n = envelopes.length;
        if (n == 0)
            return 0;
        Arrays.sort(envelopes, new Comparator<int[]>() {
            public int compare(int[] a, int[] b) {
                if (a[0] != b[0])
                    return a[0] - b[0];
                return b[1] - a[1];
            }
        });
        List<Integer> lastHeight = new ArrayList<>();
        lastHeight.add(envelopes[0][1]);
        for (int i = 1; i < n; i++) {
            int h = envelopes[i][1];
            if (h > lastHeight.get(lastHeight.size() - 1))
                lastHeight.add(h);
            else {
                int l = 0, r = lastHeight.size() - 1;
                while (r > l) {
                    int m = (l + r) >> 1;
                    if (lastHeight.get(m) < h)
                        l = m + 1;
                    else
                        r = m;
                }
                lastHeight.set(l, h);
            }
        }
        return lastHeight.size();
    }
}

完美矩形(数组、扫描线)

我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域。 每个矩形用左下角的点和右上角的点的坐标来表示。例如, 一个单位正方形可以表示为 [1,1,2,2]。 ( 左下角的点的坐标为 (1, 1) 以及右上角的点的坐标为 (2, 2) )。 示例 1:

rectangles = [ 
[1,1,3,3], 
[3,1,4,2], 
[3,2,4,4], 
[1,3,2,4], 
[2,3,3,4] ] 
返回 true。5个矩形一起可以精确地覆盖一个矩形区域。

示例 2:

rectangles = [ 
[1,1,2,3], 
[1,3,2,4], 
[3,1,4,2], 
[3,2,4,4] ] 
返回 false。两个矩形之间有间隔,无法覆盖成一个矩形。

示例 3:

rectangles = [ 
[1,1,3,3], 
[3,1,4,2], 
[1,3,2,4], 
[3,2,4,4] ] 
返回 false。图形顶端留有间隔,无法覆盖成一个矩形。

示例 4:

rectangles = [ 
[1,1,3,3], 
[3,1,4,2], 
[1,3,2,4], 
[2,2,4,4] ] 
返回 false。因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。

解答:

class Solution {
    public boolean isRectangleCover(int[][] rectangles) {
        int left = Integer.MAX_VALUE;
        int right = Integer.MIN_VALUE;
        int top = Integer.MIN_VALUE;
        int bottom = Integer.MAX_VALUE;
        int n = rectangles.length;
        Set<String> set = new HashSet<>();
        int sumArea = 0;
        for (int i = 0; i < n; i++) {
            left = Math.min(left, rectangles[i][0]);
            bottom = Math.min(bottom, rectangles[i][1]);
            right = Math.max(right, rectangles[i][2]);
            top = Math.max(top, rectangles[i][3]);
            sumArea += (rectangles[i][3] - rectangles[i][1]) * (rectangles[i][2] - rectangles[i][0]);
            String lt = rectangles[i][0] + " " + rectangles[i][3];
            String lb = rectangles[i][0] + " " + rectangles[i][1];
            String rt = rectangles[i][2] + " " + rectangles[i][3];
            String rb = rectangles[i][2] + " " + rectangles[i][1];
            if (!set.contains(lt))
                set.add(lt);
            else
                set.remove(lt);
            if (!set.contains(lb))
                set.add(lb);
            else
                set.remove(lb);
            if (!set.contains(rt))
                set.add(rt);
            else
                set.remove(rt);
            if (!set.contains(rb))
                set.add(rb);
            else
                set.remove(rb);
        }
        if (set.size() == 4 && set.contains(left + " " + top) && set.contains(left + " " + bottom)
                && set.contains(right + " " + bottom) && set.contains(right + " " + top)) {
            return sumArea == (right - left) * (top - bottom);
        }
        return false;
    }
}

本文内容到此结束了, 如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。 如有错误❌疑问💬欢迎各位大佬指出。 主页共饮一杯无的博客汇总👨‍💻

保持热爱,奔赴下一场山海。🏃🏃🏃