在柱状图中找最大矩形——O(n)时间复杂度java实现

2023-05-16


最近在刷leetcode,又碰到了这道题,想起来当时算法有些瑕疵,所以将最新的AC代码更新在最上面做个对比,具体思路见注释.


public class Solution {
    
    // 思路: 主要是使用一个栈来保存数组元素的下标,注意是保存‘下标’。
    // 入栈和出栈的规则如下:
    //    (1) 当栈为空,或者以栈顶元素tp为下标查到的heights[tp] <= heights[i]时(i为当前遍历的索引),入栈
    //    (2) 当栈顶元素tp对应的heights[tp] > heights[i]时,出栈,同时计算以heights[tp]为高,能得到的最大矩形面积
    //    (3) 当遍历完整个heights数组后,若栈不为空,则依次弹栈,同时以栈顶元素tp对应的heights[tp]为高,计算能得到的最大矩形面积
    
    public int largestRectangleArea(int[] heights) {
        if (heights == null || heights.length == 0) {
            return 0;
        }
        Stack<Integer> stack = new Stack<Integer>();
        int maxSize = 0;
        int i = 0;
        for (; i < heights.length; i++) {
            if (stack.empty() || heights[stack.peek()] <= heights[i]) {
                stack.push(i);
            } else {
                // 当前遍历元素heights[i] 比栈顶元素tp对应的heights[tp]小, 栈顶元素出栈
                int tp = stack.pop();
                int beginIndex = stack.empty() ? -1 : stack.peek(); // 当栈为空时,说明最大矩形的长度从下标0开始
                                                                    // 所以将beginIndex设置为-1
                maxSize = max(maxSize, heights[tp] * (i-1 - beginIndex));
                i--; // 由于heights[i]元素还在栈外等候,还需要继续和栈顶元素进行比较,所以i--
            }
        }
        
        while (!stack.empty()) {
            // 栈还不为空,对每个栈顶元素tp 计算以heights[tp]为高的矩形的最大面积, 并将栈顶元素出栈
            int tp = stack.pop();
            int beginIndex = stack.empty() ? -1 : stack.peek(); // 当栈为空时,说明最大矩形的长度从下标0到下标n-1,
                                                                // 所以将beginIndex设置为-1
            maxSize = max(maxSize, heights[tp] * (i-1 - beginIndex));
        }
        
        return maxSize;
    }
    
    private int max(int a, int b) {
        return a > b ? a : b;
    }
}


这次没有bug了 :)


@2016-03-07

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

最近在准备找工作,知道了这道题,用java实现了O(n)时间复杂度的算法。

    具体题目如下:给一组非负的整数来表示一个柱状图,设计一个算法获得柱状图中最大矩形的面积。比如,输入如下数据:2,1,4,5,1,3,3 ,其中每个数表示一个柱状条的高度,柱状条的宽度为默认值1,则计算得最大矩形的面积为8。

    思路:使用一个栈来保存输入柱状条,每个柱状条包含两个信息:(1)柱状条的高度(height);(2)柱状条的x坐标(index) 。数组中的柱状条按序准备入栈,入栈的条件:当入栈元素e的高度>=栈顶元素的高度时,元素e入栈;否则,将栈顶元素出栈,同时更新最大矩形maxValue的值。

    更新maxValue的算法如下:

    1. 计算以当前栈顶元素的高度为宽度的矩形的面积:tmpValue = topElement.height * (e.index - topElement.index);

    2. 更新maxValue: maxValue = (maxValue > tmpValue) ? maxValue : tmpValue;

    所有元素入栈完毕,将栈中剩余的元素依次出栈,同时按照相同的思路更新maxValue的值。

java实现:

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class MaxRectangle {

	// 使用栈来保存每个柱状条,当当前准备入栈的柱状条的高度小于当前栈顶的柱状条高度时,先让栈顶元素出栈,同时计算最大的矩形大小
	public int maxRectangleValue(int[] array) {
		if (array == null || array.length <= 0)
			return -1;
		int maxValue = 0;
		List<Element> inputList = new ArrayList<Element>();
		int len = array.length;
		for (int i = 0; i < len; i++) {
			Element element = new Element(array[i], i);
			inputList.add(element);
		}
		// 开始入栈操作
		Stack<Element> stack = new Stack<Element>();
		for (Element e : inputList) {
			if (stack.empty())
				stack.add(e);
			else {
				while (e.height < stack.peek().height) { // 出栈,并计算最大矩形大小
					Element topElement = stack.pop();
					int tmpValue = topElement.height * (e.index - topElement.index); // height * width
					if (tmpValue > maxValue)
						maxValue = tmpValue;
					if (stack.empty())
						break;
				}
				// 进栈
				stack.add(e);
			}
		}
		// 将堆栈中包含的所有元素出栈,同时更新最大的矩形大小
		while (!stack.empty()) {
			Element topElement = stack.pop();
			int tmpValue = topElement.height * ((len - 1) - topElement.index + 1); // height * width
			if (tmpValue > maxValue)
				maxValue = tmpValue;
		}
		return maxValue;
	}
	
	public static void main(String[] args) {
		int[] array = {2,1,4,5,1,3,3};
		MaxRectangle mr = new MaxRectangle();
		System.out.println(mr.maxRectangleValue(array));
	}
}

class Element {
	public int height; // 每一个柱状条的高度(宽度为1)
	public int index; // 每个柱状条的x坐标值,代表它们出现的相对次序
	public Element(int height, int index) {
		this.height = height;
		this.index = index;
	}
}
算法分析:

    所有数组元素需要一次进栈和一次出栈,所以总的时间复杂度为:O(n)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在柱状图中找最大矩形——O(n)时间复杂度java实现 的相关文章

  • Centos7安装Hive2.0.1集群

    1 准备工作 1 1 安装jdk1 8和mysql5 7 21 略 1 2 安装Hadoop2 6 0 xff0c 略 1 3 机器介绍 192 168 1 89 node1 192 168 1 149 node2 192 168 1 18
  • hive2.0.1执行存储过程

    1 编写过程sql 基于上篇文章的test db库 xff0c vi test sql xff0c 新增 xff1a use test db begin insert into t test2 id name values 2 39 你好
  • Centos7下搭建MySQL高可用架构(互为主从)

    1 环境介绍 192 168 31 14 A机器 192 168 31 82 B机器 192 168 31 200 vip xff08 A主B从 xff09 2 安装mysql 2 1 创建配置文件 xff1a vi mysql cnf m
  • JAVA基础篇-文件分片与合成实践

    本文提供两种文件分片与合成的方法 xff0c 分别是普通IO流的方式和使用RandomAccessFile的方式 xff0c 推荐RandomAccessFile方式 xff0c 接下来请看代码实现 xff1a package com st
  • GitBook快速入门

    1 安装 Node js Node 官网已经把 linux 下载版本更改为已编译好的版本了 xff0c 我们可以直接下载解压后使用 xff1a wget https nodejs org dist v10 15 3 node v10 15
  • 基于jsonp和cookie实现单点登录

    1 SSO需求 当前域名A xff1a www abc com 跨域域名B xff1a www def com 当在A域名下登录后点击链接跳转至域名B xff0c 希望实现域名B免登录 2 实现思路 2 1域名A开发一个接口C xff1a
  • 基于docker安装破解jira7.11.1

    1 拉取jira的docker镜像 docker pull cptactionhank atlassian jira software 7 11 1 2 启动jira容器 docker run name jira detach restar
  • Shell命令学习

    Shell命令 文章目录 Shell命令一 Shell是什么 xff1f 二 linux环境下的快捷键tab xff1a 输入命令或者路径等操作时自动补全上键 xff1a 快速选择上一次或多次执行的命令下键 xff1a 快速选择下一次或多次
  • 关于onNewIntent理解

    首先介绍一下Android的四种启动模式 standard 默认的 xff1a 所有的activity实例放在一个task xff08 任务栈 xff09 中 xff0c 遵循先进后出 xff0c 后进先出的规则 singleTop xff
  • ubuntu20.04系统安装谷歌浏览器

    1 百度搜索 谷歌浏览器官网 xff0c 然后在搜索界面点击如图所示图标进入谷歌浏览器下载界面 2 在谷歌浏览器下载界面 xff0c 点击 下载Chrome 3 在弹出的下载界面选择Ubuntu适用的64位下载包后点击 接受并安装 4 在下
  • 【Algorithm】单向链表模拟实现vector功能

    span class token function cmake minimum required span span class token punctuation span VERSION span class token number
  • ARCH INSTALL

    Arch Linux Install With UEFI Boot gdisk dev sdxy boot always uses less than 1G uses EF00 EFI System home uses 8302 mnt u
  • SQL Server 表注释&列注释

    添加表注释 表加注释 EXEC sys sp addextendedproperty 64 name 61 N 39 MS Description 39 64 value 61 N 39 注释内容 39 64 level0type 61 N
  • 在ubuntu14.04上安装或升级git

    git version git version 1 9 1 可以使用下面命令升级git xff08 如果不是root用户 xff0c 需在命令前加sudo xff09 xff1a add apt repository ppa git cor
  • C#串口数据处理--环形缓冲区-FIFO

    一 FIFO环形缓冲区初始化 static int MAX BUFFER LEN 61 1024 定义缓冲区大小 FIFO receiveBufferManager 61 new FIFO MAX BUFFER LEN 二 串口接收事件中添
  • IDEA 解决jar冲突问题

    在实际的 Maven 项目开发中 xff0c 由于项目引入的依赖过多 xff0c 遇到 jar 冲突算是一个很常见的问题了 如何使用 IntelliJ IDEA 解决 jar 包冲突的问题 xff01 简单粗暴 xff0c 直接上示例 xf
  • Ubuntu 18.04下安装Google Chrome

    Ubuntu 18 04下安装Google Chrome 进入Chrome官网下载地址 xff1a https www google cn intl zh CN chrome 点击 下载Chrome xff0c 进入下载页面 xff1a 如
  • css获取网页内所有标签的内容

    选择所有标签内的内容 包括script和style xff1a span class token punctuation span span class token punctuation span text 选择除script和style
  • Ubuntu 22.04 dektop 开启root并自动登录桌面

    1 设置root密码 span class token function sudo span span class token function passwd span root 2 解锁root span class token func
  • linux服务器之间的数据拷贝

    方法一 xff1a scp xff08 secure copy xff09 安全拷贝 xff08 1 xff09 scp定义 xff1a scp可以实现服务器与服务器之间的数据拷贝 xff08 from server1 to server2

随机推荐