前言
简单写个日记记录我刷了什么题以及心得总结。
刚开始刷题,没什么经验和思路,编程也有点生疏。所以前期偏向于先想后直接看别人的思路求解然后再学习了。
一、问题复述
笔直的公路上有N的路灯,从0位置开始安装,路灯间隔固定100米。
各个路灯的照明半径不尽相同,求第一个路灯到最后一个路灯之间没有被照明的路径长度和。
输入:vector int r 为每盏路灯的照亮半径,int N为路灯数。
输出:int 未照明区域的总长度
二、解法及其思想
- 需要考虑照亮半径存在过大、过小、有重叠区域等情况。
- 题目给出照亮半径,将其转化为区间表示的话可以很方便地计算。
- 使用容器vector<pair<int,int>>装载所有区间,在此基础上去除区间的重复部分。
- sort()函数允许对pair<,>进行比较,可以直接用来对区间排序。
- 排序之后即可遍历数组找出并去除重复区间。
三、代码实现及细节(仅算法相关部分)
//函数返回所求长度
int dis(vector<int> r,int N){
//step1.计算出总长
//设置合适的用于装载区间的容器:vector<pair<int,int>>
int len=100*(N-1);
vector<pair<int,int>> intervals;
//step2.装载区间:遍历半径,根据半径得出区间
//区间边界:最小为0,最大为len
int begin,end;
for(int i=0;i<N;i++){
begin=max(0,i*100-r[i]);
end=min(len,i*100+r[i]);
intervals.push_back({begin,end});
}
//step3.排序
//默认情况下,sort会根据pair的first 的值进行升序排序,当 first 相同时,会根据 second 的值进行升序排序
sort(intervals.begin(),intervals.end());
//step4.区间处理:处理重复区间
//关系到两个区间的处理,因此需要临时值
int prebegin=intervals[0].first;
int preend=intervals[0].second;
//prebegin、preend指两个区间中的前者
for(int i=1;i<N;i++){
begin=intervals[i].first;
end=intervals[i].second;
//如果后一个区间的左边界小于等于前一个区间的右边界,那么判定为重复,此时变动前一个区间的右边界
if(begin<=preend){
preend=max(preend,end);
}else{//如果不重复,可直接计算未照明长度,并前移
len-=(preend-prebegin);
prebegin=begin;
preend=end;
}
}
/*
上步中,最后一个区间与前一个区间重复了的话,照明区间没有减去;
若不重复,最后一个区间也没有计算。
无论如何,使用下面一行代码处理最后一个区间。
*/
len-=(preend-prebegin);
return len;
}
总结与感想
区间类问题头一次见。
别人的解题思路真是牛。