代码随想录算法训练营第四十二四十三天
LeetCode/卡码网题目:
- 42. 接雨水
- 84. 柱状图中最大的矩形
- 98. 所有可达路径
其他:
今日总结
往期打卡
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
往期打卡
代码随想录算法训练营第四十一天
代码随想录算法训练营第四十天
代码随想录算法训练营第三十九天
代码随想录算法训练营第三十八天
代码随想录算法训练营第三十七天
代码随想录算法训练营第三十五&三十六天
代码随想录算法训练营第三十四天
代码随想录算法训练营第三十三天(补)
代码随想录算法训练营第三十二天
代码随想录算法训练营第三十一天
代码随想录算法训练营第三十天(补)
代码随想录算法训练营第二十九天
代码随想录算法训练营第二十八天
代码随想录算法训练营第二十七天(补)
代码随想录算法训练营第二十六天
代码随想录算法训练营第二十五天
代码随想录算法训练营第二十四天
代码随想录算法训练营第二十三天
代码随想录算法训练营周末四
代码随想录算法训练营第二十二天(补)
代码随想录算法训练营第二十一天
代码随想录算法训练营第二十天
代码随想录算法训练营第十九天
代码随想录算法训练营第十八天
代码随想录算法训练营第十七天
代码随想录算法训练营周末三
代码随想录算法训练营第十六天
代码随想录算法训练营第十五天
代码随想录算法训练营第十四天
代码随想录算法训练营第十三天
代码随想录算法训练营第十二天
代码随想录算法训练营第十一天
代码随想录算法训练营周末二
代码随想录算法训练营第十天
代码随想录算法训练营第九天
代码随想录算法训练营第八天
代码随想录算法训练营第七天
代码随想录算法训练营第六天
代码随想录算法训练营第五天
代码随想录算法训练营周末一
代码随想录算法训练营第四天
代码随想录算法训练营第三天
代码随想录算法训练营第二天
代码随想录算法训练营第一天