Leetcode84 柱状图中的最大矩形
方法1:暴力法,就是找每个高度,连续的个数即可
未改进的暴力法用时:646ms,打败5.05
class Solution {
public int largestRectangleArea(int[] heights) {
Map<Integer,Integer> map=new HashMap();//存放高度以及对应,节省时间的
int res=0;
for(int i=0;i<heights.length;i++){
if(map.containsKey(heights[i])){
continue;
}
int count=0;
int max=0;
for(int j=0;j<heights.length;j++){
if(heights[j]<heights[i]){
max=Math.max(count,max);
count=0;
continue;
}
count++;
}
max=Math.max(count,max);
res=Math.max(res,max*heights[i]);
}
return res;
}
}
暴力改进,就是相同高度的,不去球了,woca 我擦 为啥时间又多了呢,我估计是map耗时了,改成数组应该会好很多。。反正用map时间居然更长了。。大概是840ms左右
class Solution {
public int largestRectangleArea(int[] heights) {
Map<Integer,Integer> map=new HashMap();//存放高度以及对应,节省时间的
int res=0;
for(int i=0;i<heights.length;i++){
if(map.containsKey(heights[i])){
continue;
}
int count=0;
int max=0;
for(int j=0;j<heights.length;j++){
if(heights[j]<heights[i]){
max=Math.max(count,max);
count=0;
continue;
}
count++;
}
max=Math.max(count,max);
map.put(heights[i],1);
res=Math.max(res,max*heights[i]);
}
return res;
}
}
类似于快排那种方法我还没有写,因为那个思路还不会,等会了再说吧,力扣里面的解析已经讲解的很好了,可以直接参考。
方法2:预处理两个数组,左边最小值数组和右边最小值数组,这个和单调栈类似,但是效率应该会高不少,虽然都是on时间复杂度,但是这个不用栈,此方法时间是2ms,击败99的用户
纠正我上面说的,我说错了,因为用栈的话不需要左右最小值数组,只需要两个变量即可了
class Solution {
public int largestRectangleArea(int[] heights) {
//每个元素左边第一个小于他的坐标数组:
if(heights.length==0||heights==null){
return 0;
}
int [] leftFirstMin=new int[heights.length];
leftFirstMin[0]=-1;
for(int i=1;i<heights.length;i++){
if(heights[i]>heights[i-1]){
leftFirstMin[i]=i-1;
continue;
}
int j=i-1;
while(j!=-1&&heights[j]>=heights[i]){
j=leftFirstMin[j];
}
leftFirstMin[i]=j;
}
//每个元素右边第一个小于他的数组:
int[] rightFirstMin=new int[heights.length];
rightFirstMin[heights.length-1]=heights.length;
for(int i=heights.length-2;i>=0;i--){
if(heights[i]>heights[i+1]){
rightFirstMin[i]=i+1;
continue;
}
int j=rightFirstMin[i+1];
while(j!=heights.length&&heights[j]>=heights[i]){
j=rightFirstMin[j];
}
rightFirstMin[i]=j;
}
//至此,左右两个数组都已经求出来了,接下来就是遍历每个柱子,然后计算面积
int res=0;
int area=0;
for(int i=0;i<heights.length;i++){
area=heights[i]*(rightFirstMin[i]-leftFirstMin[i]-1);
res=Math.max(res,area);
}
return res;
}
}
方法3,单调栈,果然用栈速度就是慢,也就是说相同复杂度的时候一定最好用基础结构吗,反正花了12ms
这里有一点注意,左神说,对于相等的处理可以用个list(栈存list)来存,这样可以得到正确的左边最小值和右边最小值,这个很重要,但是这个题你注意,如果我不这样做也不影响结果的,因为相同值中最大那个一定是正确的,而错误的一定是小的,所以我可以不用list,但是正常一定要用不能图意省事哦,这个题是个例,只限于这个题可以不用,记住 !!!! 记住!!!!!记住!!!!相同值单调栈的处理一定要记住!!!!!
class Solution {
public int largestRectangleArea(int[] heights) {
Stack<Integer> st=new Stack();
int res=0;
for(int i=0;i<heights.length;i++){
while(!st.isEmpty()&&heights[st.peek()]>heights[i]){
int height=heights[st.pop()];
int leftmin=-1;
if(!st.isEmpty()){
leftmin=st.peek();
}
int area=(i-leftmin-1)*height;
res=Math.max(res,area);
}
st.push(i);
}
while(!st.isEmpty()){
int height=heights[st.pop()];
int rightmin=heights.length;
int leftmin=-1;
if(!st.isEmpty()){
leftmin=st.peek();
}
int area=(rightmin-leftmin-1)*height;
res=Math.max(area,res);
}
return res;
}
}
大总结::数组可以模拟单调栈,而且速度提升不少,7倍哦,所以,你懂的,想秀操作不,想在面试场秀操作不,请用单调栈魔板,你用数组写bug free怕是不太现实把,老实用魔板。。。
leetcode 85(hard hard 这个是有点难了(除了暴力那个方法哈))
方法1:暴力法,但是还是有一些技巧的,有:1。数组预处理,这个就很重要,前面很多题,通过数组预处理,可以大大简化过程,这个太重要。2。边界问题,怎么做到0 bug 我写第一遍大概只出了一处错误(非边界错误,变量错误),这就是刷题的好处,刷的越多,对边界越可以控制的更好,这个只能刷题,只有这一个办法,别无他法。
过程:其实就是求每个 高度可能的1的最大值,遍历每个高度,遍历只需要沿着当前列向上遍历(因为我数组预处理的是从当前节点,左边到当前节点连续1的个数,如果你做了的不是这个预处理,那么会有一点不同)
class Solution {
public int maximalRectangle(char[][] matrix) {
if(matrix.length==0||matrix[0].length==0){
return 0;
}
int[][] help=new int[matrix.length][matrix[0].length];
//初始化数组,就是每一行连续1的个数
for(int i=0;i<matrix.length;i++){
int count=0;
for(int j=0;j<matrix[0].length;j++){
if(matrix[i][j]=='1'){
count++;
help[i][j]=count;
}else{
count=0;
}
}
}
//预处理数组已经完事
int res=0;
for(int i=0;i<matrix.length;i++){
for(int j=0;j<matrix[0].length;j++){
int i1=i;//这里出错了,如果用i,那不是sb。。我就是
int min=help[i1][j];
int height=1;
while(i1>=0&&help[i1][j]!=0){
min=Math.min(min,help[i1][j]);
int area=min*height;
res=Math.max(res,area);
height++;
i1--;
}
}
}
return res;
}
}
方法2:参看leetcode把emmmm