LeetCode/卡码网题目:
其他:
42. 接雨水
跳转: 42. 接雨水
学习: 代码随想录公开讲解
问题:
给定 n
个非负整数表示每个宽度为 1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
思路:
单调栈的思路是只有遇到递增时才有可能能兜住雨水
单调栈中记录好右边界(填充边界之间的元素),如果当前柱子大于栈顶右边界,就要用栈中前一个边界或当前柱子中最小的那个填充洼地.
如果没有前一个边界,那么就说明前面都是已经填过的更小的值,兜不住雨水.
遍历时一共有三种情况:
栈为空或当前比栈顶小
当前和栈顶一样
当前大于栈顶
一样就要更新右边界,大于就开始出栈并填充
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
代码:
class Solution {
public int trap(int[] height) {
Deque<Integer> stack = new LinkedList<>();
int ans = 0;
for(int i=0;i<height.length;i++){
if(!stack.isEmpty()){
if(height[stack.peekLast()]==height[i]){
stack.pollLast();
}
else if(height[stack.peekLast()]<height[i]){
do{
int mid = stack.pollLast();
if(!stack.isEmpty()){
int h = Math.min(height[stack.peekLast()],height[i])-height[mid];
int w = i - stack.peekLast()-1;
ans+=h*w;
}
}while(!stack.isEmpty()&&height[stack.peekLast()]<height[i]);
}
}
stack.add(i);
}
return ans;
}
}
84. 柱状图中最大的矩形
跳转: 84. 柱状图中最大的矩形
学习: 代码随想录公开讲解
问题:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
思路:
如果递减,就开始计算前面一直到和自己等高那一块儿里的最大矩形.
再往后的计算不会和比当前元素高的部分合并,所以去掉的部分都会被看作当前元素.
为了让最小的元素能从0算到i-1,需要在最开始加一个高度为0的最小的柱子(哪怕被更新了0高度本来也是不需要计算的)
最后一个元素添加完后形成的递增栈也需要计算,可以从尾部再加一个为0的元素,将剩余可选矩阵全部计算求最大值
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
代码:
class Solution {
public int largestRectangleArea(int[] height) {
Deque<Integer> stack = new LinkedList<>();
int n = height.length+2;
int[] heights = new int[n];
System.arraycopy(height, 0, heights, 1, height.length);
int ans = 0;
stack.add(0);
for(int i=1;i<n;i++){
if(heights[i]>heights[stack.peekLast()]){
stack.add(i);
}
else if(heights[i]==heights[stack.peekLast()]){
stack.pollLast();
stack.add(i);
}
else{
while(!stack.isEmpty()&&heights[i]<=heights[stack.peekLast()]){
int mid = stack.pollLast();
if(!stack.isEmpty()){
int w = i-stack.peekLast()-1;
int h = heights[mid];
ans = Math.max(ans,w*h);
}
}
stack.add(i);
}
}
return ans;
}
}
98. 所有可达路径
跳转: 98. 所有可达路径
学习: 代码随想录公开讲解
问题:
给定一个有 n 个节点的有向无环图,节点编号从 1 到 n。请编写一个函数,找出并返回所有从节点 1 到节点 n 的路径。每条路径应以节点编号的列表形式表示。
思路:
从1开始,dfs深搜路径,回溯,结束条件是到达n,题目中说明了不会有平行边和自环,所以深度有限不用担心爆栈.
使用动态数组构造有向图的邻接矩阵,比使用基本数组要节省空间
复杂度:
- 时间复杂度: O ( m ) O(m) O(m)
- 空间复杂度: O ( m ) O(m) O(m)
代码:
import java.util.*;
class Main {
static List<Integer>[] lists;
static ArrayList<Integer> path = new ArrayList<>();
static boolean flag = true;
static void dfs(int start) {
if(start==lists.length-1){
flag = false;
System.out.print(1);
for(int i=0;i<path.size();i++){
System.out.print(" "+path.get(i));
}
System.out.println("");
return;
}
for(int i:lists[start]){
path.add(i);
dfs(i);
path.remove(path.size()-1);
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int M = in.nextInt();
lists = new List[N + 1];
for (int i = 0; i <= N; i++) {
lists[i] = new ArrayList<>();
}
for (int i = 0; i < M; i++) {
int x = in.nextInt();
int y = in.nextInt();
lists[x].add(y);
}
dfs(1);
if(flag) System.out.println(-1);
}
}
总结
练习了单调栈和DFS