【LeetCode/LintCode】 题解丨微软面试题:大楼轮廓
水平面上有 N 座大楼,每座大楼都是矩阵的形状,可以用一个三元组表示 (start, end, height),分别代表其在x轴上的起点,终点和高度。大楼之间从远处看可能会重叠,求出 N 座大楼的外轮廓线。
外轮廓线的表示方法为若干三元组,每个三元组包含三个数字 (start, end, height),代表这段轮廓的起始位置,终止位置和高度。
点击进入在线评测
样例1
输入:
[
[1, 3, 3],
[2, 4, 4],
[5, 6, 1]
]
输出:
[
[1, 2, 3],
[2, 4, 4],
[5, 6, 1]
]
说明:
建筑物如下图所示,黄色部分表示建筑物
样例2
输入:
[
[1, 4, 3],
[6, 9, 5]
]
输出:
[
[1, 4, 3],
[6, 9, 5]
]
说明:
建筑物如下图所示,黄色部分表示建筑物
【题解】
使用[九章算法强化班]中讲过的 HashHeap 和扫描线算法。 Java 可以用 TreeSet / TreeMap, C++ 可以用 Map.
import java.util.*;
public class Solution {
class HashHeap {
ArrayList<Integer> heap;
String mode;
int size_t;
HashMap<Integer, Node> hash;
class Node {
public Integer id;
public Integer num;
Node(Node now) {
id = now.id;
num = now.num;
}
Node(Integer first, Integer second) {
this.id = first;
this.num = second;
}
}
public HashHeap(String mod) {
// TODO Auto-generated constructor stub
heap = new ArrayList<Integer>();
mode = mod;
hash = new HashMap<Integer, Node>();
size_t = 0;
}
public int peek() {
return heap.get(0);
}
public int size() {
return size_t;
}
public Boolean isEmpty() {
return (heap.size() == 0);
}
int parent(int id) {
if (id == 0) {
return -1;
}
return (id - 1) / 2;
}
int lson(int id) {
return id * 2 + 1;
}
int rson(int id) {
return id * 2 + 2;
}
boolean comparesmall(int a, int b) {
if (a <= b) {
if (mode == "min")
return true;
else
return false;
} else {
if (mode == "min")
return false;
else
return true;
}
}
void swap(int idA, int idB) {
int valA = heap.get(idA);
int valB = heap.get(idB);
int numA = hash.get(valA).num;
int numB = hash.get(valB).num;
hash.put(valB, new Node(idA, numB));
hash.put(valA, new Node(idB, numA));
heap.set(idA, valB);
heap.set(idB, valA);
}
public Integer poll() {
size_t--;
Integer now = heap.get(0);
Node hashnow = hash.get(now);
if (hashnow.num == 1) {
swap(0, heap.size() - 1);
hash.remove(now);
heap.remove(heap.size() - 1);
if (heap.size() > 0) {
siftdown(0);
}
} else {
hash.put(now, new Node(0, hashnow.num - 1));
}
return now;
}
public void add(int now) {
size_t++;
if (hash.containsKey(now)) {
Node hashnow = hash.get(now);
hash.put(now, new Node(hashnow.id, hashnow.num + 1));
} else {
heap.add(now);
hash.put(now, new Node(heap.size() - 1, 1));
}
siftup(heap.size() - 1);
}
public void delete(int now) {
size_t--;
Node hashnow = hash.get(now);
int id = hashnow.id;
int num = hashnow.num;
if (hashnow.num == 1) {
swap(id, heap.size() - 1);
hash.remove(now);
heap.remove(heap.size() - 1);
if (heap.size() > id) {
siftup(id);
siftdown(id);
}
} else {
hash.put(now, new Node(id, num - 1));
}
}
void siftup(int id) {
while (parent(id) > -1) {
int parentId = parent(id);
if (comparesmall(heap.get(parentId), heap.get(id)) == true) {
break;
} else {
swap(id, parentId);
}
id = parentId;
}
}
void siftdown(int id) {
while (lson(id) < heap.size()) {
int leftId = lson(id);
int rightId = rson(id);
int son;
if (rightId >= heap.size()
|| (comparesmall(heap.get(leftId), heap.get(rightId)) == true)) {
son = leftId;
} else {
son = rightId;
}
if (comparesmall(heap.get(id), heap.get(son)) == true) {
break;
} else {
swap(id, son);
}
id = son;
}
}
}
class Edge {
int pos;
int height;
boolean isStart;
public Edge(int pos, int height, boolean isStart) {
this.pos = pos;
this.height = height;
this.isStart = isStart;
}
}
class EdgeComparator implements Comparator<Edge> {
@Override
public int compare(Edge arg1, Edge arg2) {
Edge l1 = (Edge) arg1;
Edge l2 = (Edge) arg2;
if (l1.pos != l2.pos)
return compareInteger(l1.pos, l2.pos);
if (l1.isStart && l2.isStart) {
return compareInteger(l2.height, l1.height);
}
if (!l1.isStart && !l2.isStart) {
return compareInteger(l1.height, l2.height);
}
return l1.isStart ? -1 : 1;
}
int compareInteger(int a, int b) {
return a <= b ? -1 : 1;
}
}
List<List<Integer>> output(List<List<Integer>> res) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
if (res.size() > 0) {
int pre = res.get(0).get(0);
int height = res.get(0).get(1);
for (int i = 1; i < res.size(); i++) {
List<Integer> now = new ArrayList<Integer>();
int id = res.get(i).get(0);
if (height > 0) {
now.add(pre);
now.add(id);
now.add(height);
ans.add(now);
}
pre = id;
height = res.get(i).get(1);
}
}
return ans;
}
public List<List<Integer>> buildingOutline(int[][] buildings) {
// write your code here
List<List<Integer>> res = new ArrayList<List<Integer>>();
if (buildings == null || buildings.length == 0
|| buildings[0].length == 0) {
return res;
}
ArrayList<Edge> edges = new ArrayList<Edge>();
for (int[] building : buildings) {
Edge startEdge = new Edge(building[0], building[2], true);
edges.add(startEdge);
Edge endEdge = new Edge(building[1], building[2], false);
edges.add(endEdge);
}
Collections.sort(edges, new EdgeComparator());
HashHeap heap = new HashHeap("max");
List<Integer> now = null;
for (Edge edge : edges) {
if (edge.isStart) {
if (heap.isEmpty() || edge.height > heap.peek()) {
now = new ArrayList<Integer>(Arrays.asList(edge.pos,
edge.height));
res.add(now);
}
heap.add(edge.height);
} else {
heap.delete(edge.height);
if (heap.isEmpty() || edge.height > heap.peek()) {
if (heap.isEmpty()) {
now = new ArrayList<Integer>(Arrays.asList(edge.pos, 0));
} else {
now = new ArrayList<Integer>(Arrays.asList(edge.pos,
heap.peek()));
}
res.add(now);
}
}
}
return output(res);
}
}
更多题解参见:九章官网
【LeetCode/LintCode】 题解丨微软面试题:大楼轮廓的更多相关文章
- 【LeetCode/LintCode】丨Google面试题:N皇后问题
n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线). 给定一个整数n,返回所有不同的n皇后问题的解决方案. 每个解决方案包含一个明确的 ...
- leetcode & lintcode 题解
刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...
- [leetcode/lintcode 题解] 微软面试题:股票价格跨度
编写一个 StockSpanner 类,它收集某些股票的每日报价,并返回该股票当日价格的跨度. 今天股票价格的跨度被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天). 例如 ...
- [leetcode/lintcode 题解] 微软面试题:公平索引
现在给你两个长度均为N的整数数组 A 和 B. 当(A[0]+...A[K-1]),(A[K]+...+A[N-1]),(B[0]+...+B[K-1]) 和 (B[K]+...+B[N-1])四个和 ...
- [leetcode/lintcode 题解] 微软 面试题:实现 Trie(前缀树)
实现一个 Trie,包含 insert, search, 和 startsWith 这三个方法. 在线评测地址:领扣题库官网 样例 1: 输入: insert(" ...
- 【LeetCode/LintCode】 题解丨字节跳动试题:第k大的子数组
给定一个长度为n的数组a,它有n(n+1)/2个子数组.请计算这些子数组的和,然后按照升序排列,并返回排序后第k个数. 1≤n≤10^5 1≤ai≤10^9 1≤k≤n(n+1)/2 在线 ...
- [leetcode/lintcode 题解] Amazon面试题:连接棒材的最低费用
为了装修新房,你需要加工一些长度为正整数的棒材 sticks. 如果要将长度分别为 X 和 Y 的两根棒材连接在一起,你需要支付 X + Y 的费用. 由于施工需要,你必须将所有棒材连接成一根. 返回 ...
- [leetcode/lintcode 题解] 谷歌面试题:找出有向图中的弱连通分量
请找出有向图中弱连通分量.图中的每个节点包含 1 个标签和1 个相邻节点列表.(有向图的弱连通分量是任意两点均有有向边相连的极大子图) 将连通分量内的元素升序排列. 在线评测地址:https://ww ...
- [leetcode/lintcode 题解] Google面试题:合法组合
给一个单词s,和一个字符串集合str.这个单词每次去掉一个字母,直到剩下最后一个字母.求验证是否存在一种删除的顺序,这个顺序下所有的单词都在str中.例如单词是’abc’,字符串集合是{‘a’,’ab ...
随机推荐
- Go的100天之旅-04基础数据类型
基础数据类型 在变量的定义中,我们讲了每个变量是有类型的,类型在计算机中是用来约束数据的解释.Go语言和其它计算机语言一样,提供丰富了丰富的数据类型,我们就来看看到底有哪些类型,同时也可以比较一下它和 ...
- 三种安装python第三方库的方法
还记得第一天的时候我们说python拥有丰富的库,那这么多的第三方库,我们如何使用呢?今天我们可以看一下python库的安装. 方法一:使用python命令进行离线安装 我以urllib5库 ...
- 史上最全的 jmeter 获取 jdbc 数据使用的四种方法
jmeter使用jdbc协议获取数据库中数据,很多人都会用,因为大家在做测试的时候,有时候需要大量的用户进行登录,获取需要数据库中真实的数据用于测试,所以常常会用jdbc来获取数据库数据. 那从数据库 ...
- Ethical Hacking - NETWORK PENETRATION TESTING(9)
WEP Cracking Packet Injection What if the AP was idle, or had no clients associated with it? In this ...
- git配置httpd服务-web_dav模式
1,搭建httpd应用 2,修改httpd.conf文件 注释 DocumentRoot "/data/httpd/htdocs" 注释 <Directory "/ ...
- react实战 : 用矩阵思想做一个自适应布局容器组件
需求是这样的. 有一个需要显示若干方块型元素的小区域 数量比较少的时候显示一排 数量比较多的时候显示两排 用 grid 不好,因为当数量为奇数的时候需要两排里面的元素都乖乖的居中显示. 用 flex ...
- windows下nginx问题:[crit] 796#7096: *1 GetFileAttributesEx() "F: ginx-1.12.2\html\dist" failed (123: The filename, directory name, or volume label syntax is incorrect), client: 127.0.0.1, server: localho
错误信息: 2019/09/09 13:54:37 [crit] 796#7096: *1 GetFileAttributesEx() "F: ginx-1.12.2\html\dist&q ...
- spring学习(三)属性注入
用的是IDEA的maven工程,pom.xml文件导包依赖省略 本文主要写set方式注入 (一).一般类型注入 一.写两个实体类Car.User public class Car { private ...
- 第33课 C++中的字符串
1. 历史遗留问题及解决方案 (1)历史遗留问题 ①C语言不支持真正意义上的字符串------c语言是用字符数组实现字符串 ②C语言用字符数组和一组函数模拟字符串操作 ③C语言不支持自定义类型,因此无 ...
- bubble排序
故事的起因:好久没有用bubble了,,,居然忘记了基本格式........ 经过:,,,,这可算是我学的第一个比较有用的"算法"啊...这怎么行! 结果: void bubbleSort (elem ...