第十八天
1765 地图中的最高点
给你一个大小为 m x n
的整数矩阵isWater
,它代表了一个由 陆地 和 水域 单元格组成的地图。
-
如果
isWater[i][j] == 0
,格子(i, j)
是一个 陆地 格子。 -
如果
isWater[i][j] == 1
,格子(i, j)
是一个 水域 格子。
你需要按照如下规则给每个单元格安排高度:
-
每个格子的高度都必须是非负的。
-
如果一个格子是是 水域 ,那么它的高度必须为
0
。 -
任意相邻的格子高度差 至多 为
1
。当两个格子在正东、南、西、北方向上相互紧挨着,就称它们为相邻的格子。(也就是说它们有一条公共边)
找到一种安排高度的方案,使得矩阵中的最高高度值 最大 。
请你返回一个大小为 m x n
的整数矩阵height
,其中 height[i][j]
是格子 (i, j)
的高度。如果有多种解法,请返回 任意一个 。
方法 广度优先搜索
本题的解题思路和之前的542 01矩阵题相同,在此不再赘述解题思路。
class Solution {
public static boolean[][] isVisited;
public static int[] dx = {0, 0, 1, -1};
public static int[] dy = {1, -1, 0, 0};
public static int xlength;
public static int ylength;
public int[][] highestPeak(int[][] isWater) {
xlength = isWater.length;
ylength = isWater[0].length;
isVisited = new boolean[xlength][ylength];
Queue<int[]> queue = new LinkedList<>();
int[][] res = new int[xlength][ylength];
for (int i = 0; i < xlength; ++i){
for (int j = 0; j < ylength; ++j){
if (isWater[i][j] == 1){
queue.offer(new int[]{i, j, 0});
isVisited[i][j] = true;
res[i][j] = 0;
}
}
}
while (!queue.isEmpty()){
int[] temp = queue.poll();
int x = temp[0];
int y = temp[1];
int height = temp[2];
isVisited[x][y] = true;
for (int i = 0; i < 4; ++i){
if (isValid(x + dx[i], y + dy[i])){
res[x + dx[i]][y + dy[i]] = height + 1;
queue.offer(new int[]{x + dx[i], y + dy[i], height + 1});
isVisited[x + dx[i]][y + dy[i]] = true;
}
}
}
return res;
}
public static boolean isValid(int x, int y){
return x >= 0 && x < xlength && y >= 0 && y < ylength && !isVisited[x][y];
}
}
844 比较含退格的字符串
给定s
和 t
两个字符串,当它们分别被输入到空白的文本编辑器后,请你判断二者是否相等。#
代表退格字符。
如果相等,返回 true
;否则,返回 false
。
**注意:**如果对空文本输入退格字符,文本继续为空。
方法
使用两个栈来记录两个字符串的操作,遇到#
时就将栈顶的元素弹出即可。
class Solution {
public boolean backspaceCompare(String s, String t) {
Stack<Character> a = new Stack<>();
Stack<Character> b = new Stack<>();
for (int i = 0; i < s.length(); ++i){
if (s.charAt(i) == '#') {if (!a.isEmpty()) a.pop();}
else a.push(s.charAt(i));
}
for (int j = 0; j < t.length(); ++j){
if (t.charAt(j) == '#') {if (!b.isEmpty()) b.pop();}
else b.push(t.charAt(j));
}
while (!a.isEmpty()){
if (b.isEmpty()) return false;
if(a.pop() != b.pop()) return false;
}
return b.isEmpty();
}
}
986 区间的交集
给定两个由一些 闭区间 组成的列表,firstList
和 secondList
,其中 firstList[i] = [starti, endi]
而 secondList[j] = [startj, endj]
。每个区间列表都是成对 不相交 的,并且 已经排序 。
返回这 两个区间列表的交集 。
形式上,闭区间 [a, b]
(其中 a <= b
)表示实数x
的集合,而 a <= x <= b
。
两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3]
和 [2, 4]
的交集为[2, 3]
。
方法
使用两个指针s
和e
来标记交集的区间的开始点和结束点,两个区间指针index1
和index2
来分别标记当前已经遍历到第一个区间序列的第几个区间和第二个区间序列的第几个区间。根据交集的定义,s
应当是当前遍历到的两个区间的开始位置的最大值,e
应该是两个区间的结束位置的最小值,存在以下几种情况:
s>=e
,表明当前遍历到的区间有交集,我们将[s,e]
区间放到结果中去。此时需要考虑是哪一个区间提供了e
,换言之,我们需要确定是哪一个区间的结束位置更小。因为结束位置较大的那个区间还有和下一个区间相交的可能,此时我们应当保持结束位置大的区间的index
不动,而让那个结束位置小的区间的index
加一即可,也就是说明这个区间用完了,需要拿下一个区间来做比较。s<e
,表明当前遍历到的两个区间没有交集,但是此时我们并不能笼统的将两个序列的index
值都加上一,因为和第一种情况一样,结束位置较大的那个区间可能会和下一个区间相交,因此,index
值的更新策略和第一种情况一致。
class Solution {
public int[][] intervalIntersection(int[][] firstList, int[][] secondList){
int index1 = 0, index2 = 0;
int s = 0, e = 0;
ArrayList<int[]> resArray = new ArrayList<>();
while (index1 <= firstList.length - 1 && index2 <= secondList.length - 1){
s = Math.max(firstList[index1][0], secondList[index2][0]);
e = Math.min(firstList[index1][1], secondList[index2][1]);
if (s <= e) resArray.add(new int[]{s, e});
if (e == firstList[index1][1]) index1++;
else index2++;
}
int[][] res = new int[resArray.size()][2];
int index = 0;
for (int[] temp : resArray) res[index++] = temp;
return res;
}
}
11 盛最多水的容器
给你n
个非负整数a1,a2,...,an,
每个数代表坐标中的一个点 (i, ai)
。在坐标内画n
条垂直线,垂直线i
的两个端点分别为 (i, ai)
和(i, 0)
。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
方法 贪心
定义两个指针i
,j
分别指向序列的开始和结束位置。由于我们需要求出最大的盛水面积,依据题意,我们直到,如果知道了容器的开始位置和结束位置,那么盛水量为
(
j
−
i
)
∗
m
i
n
(
h
e
i
g
h
t
[
i
]
,
h
e
i
g
h
t
[
j
]
)
(j-i)*min(height[i],height[j])
(j−i)∗min(height[i],height[j])
考虑如何移动i
和j
,由于i
只往右移动,而j
只往左移动。height[i]
和height[j]
存在一个大小关系,现假设height[i]<height[j]
。由于盛水量只和小的那个值有关,如果我们移动较大的那个值,整体的盛水量不会发生变化,因此我们应当让值小的一边发生移动。
当i
增加时,此时等价于问题的规模减少了1
,又回到的一开始讨论的状态。当遍历完之后,记录最大值即可。
class Solution {
public int maxArea(int[] height) {
int i = 0, j = height.length - 1;
int res = area(height, i, j);
while (i < j){
if (height[i] < height[j]) i++;
else j--;
res = Math.max(res, area(height, i, j));
}
return res;
}
public static int area(int[] height, int i, int j){
return (j - i) * Math.min(height[i], height[j]);
}
}