大楼轮廓 算法解析

题目来源 点击打开链接

这道题经过好多次修改,,最主要是时间复杂度问题。


下面讲讲思路:

第一个重要转化是将所有矩形转变为向上跳变和向下跳变两种情况。之后对所有的上跳变和下跳变排序。用vector。
需要另一个容器用来维护当前的高度。当前重叠高度height必须是一个可检索的存储方式。

height一开始使用vector 但是涉及到非常多的插入和删除操作,所以改为链表,而且使用不删除的形式,链表中每个节点使用一个count来实现该高度是否存在。

bool operator< (const Rect_fun &a) const

这个逻辑很重要,对于建立好的上下跳变的vector,首先根据x进行排序(x小的排在前面),其次对于相同的x,根据flag排序,flag==1向上跳变排在前面,最后对于相同x相同flag,向上跳变的高度排在前面,向下跳变的高度排在后面。

struct HeightNode
{
	int h;
	int count;
	HeightNode *next;

	HeightNode(int hh, int cc): h(hh), count(cc), next(NULL){}
};
int findHeightMax(HeightNode *ptr)
{
	int max = 0;
	while(ptr != NULL)
	{
		if(ptr->h > max && ptr->count > 0)
			max = ptr->h;
		ptr = ptr->next;
	}
	return max;
}
int getHeightSize(HeightNode *ptr)//可优化
{
	int count=0;
	while(ptr != NULL)
	{
		count += ptr->count;
		ptr = ptr->next;
	}
	return count;
}
void deleteHeight(HeightNode *ptr, int ii)
{
	while(ptr != NULL)
	{
		if(ptr->h == ii)
		{
			ptr->count--;
		}
		ptr = ptr->next;
	}
}
void addHeight(HeightNode *ptr, int ii)
{
	while(1)
	{
		if(ptr->h == ii)
		{
			ptr->count++;
			return ;
		}
		if(ptr->next != NULL)
			ptr = ptr->next;
		else
			break;
	}
	//如果没找到
	HeightNode *p = new HeightNode(ii,1);
	ptr->next = p;
	

}

 struct Rect_fun
{
    int x;
    bool flag;//1是向上跳变 0是向下跳变
	int height;
	
	Rect_fun(int xx, int f, int h) : x(xx), flag(f), height(h){}

	//对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
	bool operator< (const Rect_fun &a)  const
    {
		if(x != a.x)
			return x<a.x;
		else
		{
			if(flag !=a.flag)
				return flag>a.flag;
			else
			{
				if(flag==1)
					return height>a.height;
				else
					return height<a.height;
			}
		}
    }
};

class Solution {
public:
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    
	vector<vector<int>> buildingOutline(vector<vector<int> > &buildings) {

		vector<vector<int>> out;//输出的结果
		vector<Rect_fun> state;

		vector<int> now_height;//当前的高度
		HeightNode p_item(0,0);
		HeightNode *p_height = &p_item;
		

		int height_temp = 0;
		int height_x = 0;//向上跳变时x的起点
		bool height_flag = 0;//是否在构建新的矩形

		for(int i=0; i<buildings.size(); i++)//获得跳变沿的信息,之后对所有跳变沿排序
		{
			Rect_fun temp1(buildings.at(i).at(0), 1, buildings.at(i).at(2));
			Rect_fun temp2(buildings.at(i).at(1), 0, buildings.at(i).at(2));
			state.push_back(temp1);
			state.push_back(temp2);
		}
		sort(state.begin(),state.end());

		for(int i=0; i<state.size(); i++)
		{
			if(state.at(i).flag == 1)//如果是上升沿
			{
				//now_height.push_back(state.at(i).height);
				addHeight(p_height,state.at(i).height);
				if(0 == height_flag)//如果之前没有矩形
				{
					height_x = state.at(i).x;//记录下当前跳变沿的位置
					height_temp = state.at(i).height;//记录下当前的高度
					height_flag = 1;
				}
				else
				{
					if(state.at(i).height > height_temp)
					{
						vector<int> temp;
						temp.push_back(height_x);
						temp.push_back(state.at(i).x);
						temp.push_back(height_temp);
						out.push_back(temp);

						height_x = state.at(i).x;
						height_temp = state.at(i).height;
					}
				}
			}
			if(state.at(i).flag == 0)//如果是下降沿
			{
				//vector<int>::iterator iter=find(now_height.begin(), now_height.end(), state.at(i).height);
				//now_height.erase(iter);
				deleteHeight(p_height, state.at(i).height);

				//if(now_height.size() != 0)
				if(getHeightSize(p_height) != 0)
				{
					if(state.at(i).height != height_temp)//当去除的节点不是最大值,可以忽略
					{
						continue;
					}
					//int max_temp = *max_element(now_height.begin(),now_height.end());
					int max_temp = findHeightMax(p_height);
                    if(max_temp <  height_temp  && height_x != state.at(i).x)//当前向下跳变比之前低,如果想下跳是最大值,但是有两个最大值,这句话可以避免问题
					{
					vector<int> temp;
					temp.push_back(height_x);
					temp.push_back(state.at(i).x);
					temp.push_back(height_temp);
					out.push_back(temp);

					height_x = state.at(i).x;
					height_temp = max_temp;
					}
					
				}
				else//向下跳变到0
				{
					vector<int> temp;
					temp.push_back(height_x);
					temp.push_back(state.at(i).x);
					temp.push_back(height_temp);
					out.push_back(temp);

					height_x = 0;
					height_temp =0;
					height_flag = 0;

				}
			}
		}
		return out;
        // write your code here
    }
};



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算机算法分析与设计 计算机算法分析与设计(共33张PPT)全文共33页,当前为第1页。 学习目标 掌握算法分析与设计的基本理论 掌握进行算法分析与设计的基本方法(时间、空间复杂度分析,算法正确性的证明) 掌握计算机领域中常用的非数值计算方法,并学会用这些算法解决实际问题 计算机算法分析与设计(共33张PPT)全文共33页,当前为第2页。 课程要求 教学方式:理论(32学时),实践(16学时) 考核方式:考试(80%)+实验作业(20%) 课程学分:3 先修课程:《离散数学》《数据结构》《数值分析》《C语言程序设计》 计算机算法分析与设计(共33张PPT)全文共33页,当前为第3页。 授课教材 选用教材: 《计算机算法基础》(第二版) 余祥宣,崔国华,邹海明 华中科技大学出版社 参考书目: 《算法引论》 张益新,沈雁 国防科技大学出版社 《算法设计与分析》 周培德 机械工业出版社 计算机算法分析与设计(共33张PPT)全文共33页,当前为第4页。 第一章 导引 ---计算机算法分析与设计是面向设计的、处于核心地位的教育课程 ---计算机算法是计算机科学和计算机应用的核心。 1.什么是算法? 2.如何分析算法? 3.如何表示算法? 4.基本数据结构 计算机算法分析与设计(共33张PPT)全文共33页,当前为第5页。 1.什么是算法 算法 数值计算方法(求解数值问题,插值计算、数值积分等) 非数值计算方法(求解非数值问题,主要进行判断比较) 算法笼统的定义:求解一确定类问题的任意一种特殊方法。 非形式描述:算法就是一组有穷的规则,它规定了解决某一特定类型问题的一系列运算。 计算机算法分析与设计(共33张PPT)全文共33页,当前为第6页。 例1 求两个正整数m,n的最大公因子 算法1-1 欧几里得算法 输入:正整数m和n 输出:m和n的最大公因子 第一步:求余数。r m%n 第二步:判断r=0?,若是,终止(n为答案),否则,转第三步。 第三步:互换,m n,n r,返回第一步。 Begin R m%n r=0? Swap(m.n) End N Y 计算机算法分析与设计(共33张PPT)全文共33页,当前为第7页。 例1 求两个正整数最大公因子的一个实例 假设 m=21 和 n=45,求21和45的最大公因子 第一步:r=m%n=21%45=21; 第二步:r 不等于0,转入第三步; 第三步:互换,m=n=45, n=r=21,返回第一步。 第一步:r=m%n=45%21=3; 第二步:r 不等于0,转入第三步; 第三步:互换,m=n=21, n=r=3,返回第一步。 第一步:r=m%n=21%3=0; 第二步:r 等于0,算法结束,3即为21和45的最大公因子。 计算机算法分析与设计(共33张PPT)全文共33页,当前为第8页。 算法的五个重要特性 确定性 每一种运算必须要有确切的定义,无二义性 可行性 运算都是基本运算,原理上能在有限时间内完成 输入 有 1个或多个输入 输出 一个或多个输出 有穷性 在执行了有穷步运算后终止 计算机算法分析与设计(共33张PPT)全文共33页,当前为第9页。 算法的特性 凡是算法,都必须满足以上五条特性。 只满足前四条特性的一组规则不能称之为算法,只能叫做计算过程。 操作系统就是计算过程的一个典型例子。设计操作系统的目的是为了控制作业的运行,当没有作业时,这一计算过程并不终止,而是处于等待状态,一直等到一个新的作业的进入。 计算机算法分析与设计(共33张PPT)全文共33页,当前为第10页。 算法学习的五个内容 如何设计算法 运用一些基本设计策略规划算法 如何表示算法 用恰当的方式表示算法 如何确认算法 算法正确性的证明(算法确认algorithm validation) 如何分析算法 通过时间和空间复杂度的分析,确定算法的优劣 如何测试程序 测试程序是否会产生错误的结果 计算机算法分析与设计(共33张PPT)全文共33页,当前为第11页。 2.如何分析算法 算法分析是对一个算法需要多少计算时间和存储空间作定量的分析。 算法分析步骤: 首先确定使用那些运算以及执行这些运算所用的时间。(运算包括基本数值运算和一些更基本的任意长序列的运算) 其次是要确定出能反映算法在各种情况下工作的数据集。(即要求我们编造出能产生最好、最坏和有代表性情况的数据配置,通过使用这些数据来运行算法,以更了解算法的性能) 计算机算法分析与设计(共33张PPT)全文共33页,当前为第12页。 全面分析一个算法的两个阶段 事前分析(a priori analysis) 求出该算法的一个时间限界函数(一些关于参数的函数) 事前分析只限于每条语句的频率计数(frequency count,该语句的执行次数,与所用的机器无关,且独
㈠ 点的基本运算 1. 平面上两点之间距离 1 2. 判断两点是否重合 1 3. 矢量叉乘 1 4. 矢量点乘 2 5. 判断点是否在线段上 2 6. 求一点饶某点旋转后的坐标 2 7. 求矢量夹角 2 ㈡ 线段及直线的基本运算 1. 点与线段的关系 3 2. 求点到线段所在直线垂线的垂足 4 3. 点到线段的最近点 4 4. 点到线段所在直线的距离 4 5. 点到折线集的最近距离 4 6. 判断圆是否在多边形内 5 7. 求矢量夹角余弦 5 8. 求线段之间的夹角 5 9. 判断线段是否相交 6 10.判断线段是否相交但不交在端点处 6 11.求线段所在直线的方程 6 12.求直线的斜率 7 13.求直线的倾斜角 7 14.求点关于某直线的对称点 7 15.判断两条直线是否相交及求直线交点 7 16.判断线段是否相交,如果相交返回交点 7 ㈢ 多边形常用算法模块 1. 判断多边形是否简单多边形 8 2. 检查多边形顶点的凸凹性 9 3. 判断多边形是否凸多边形 9 4. 求多边形面积 9 5. 判断多边形顶点的排列方向,方法一 10 6. 判断多边形顶点的排列方向,方法二 10 7. 射线法判断点是否在多边形内 10 8. 判断点是否在凸多边形内 11 9. 寻找点集的graham算法 12 10.寻找点集凸包的卷包裹法 13 11.判断线段是否在多边形内 14 12.求简单多边形的重心 15 13.求凸多边形的重心 17 14.求肯定在给定多边形内的一个点 17 15.求从多边形外一点出发到该多边形的切线 18 16.判断多边形的核是否存在 19 ㈣ 圆的基本运算 1 .点是否在圆内 20 2 .求不共线的三点所确定的圆 21 ㈤ 矩形的基本运算 1.已知矩形三点坐标,求第4点坐标 22 ㈥ 常用算法的描述 22 ㈦ 补充 1.两圆关系: 24 2.判断圆是否在矩形内: 24 3.点到平面的距离: 25 4.点是否在直线同侧: 25 5.镜面反射线: 25 6.矩形包含: 26 7.两圆交点: 27 8.两圆公共面积: 28 9. 圆和直线关系: 29 10. 内切圆: 30 11. 求切点: 31 12. 线段的左右旋: 31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值