1. 在函数中的形参为引用的形式可以大大的提升时间。增幅接近一倍!!!而且也大大的节省了空间!!!
就算是字符串类型也是一样,字符串传参主要是地址的传入,计算机依旧申请了空间,这样就加大了内存的使用,并且减慢的速度。
2. 在元素有规律的数据结构中进行查找,可以采用一边比较一边排序的方法。
因为这种情况的特殊性,可以在结构取一种中间值,与目标值进行比较,如果等于目标值则找到答案,
有两个值i和j可以来调节值的大小,如果大于则调节i和j来增大中间值,小于则调小、
3. 一个可以分为许多有联系的子集的问题时可以用动态规划来解决
有一种递推关系在里面,分成许多个子集,而且子集之间能够找到一种对应的关系,答案的形式并不固定,有时候可能让你选最大值,有时候是一个vector,有时候是最小值,但是在解决问题的过程中如果出现了考虑子集的流程,出现了将一个大问题分为很多小问题的想法,就不要在多想了,dp吧少年!!!
4. 关于sort函数以及优先队列priority_queue的用法
sort 函数包括在头文件为algorithm中,它的参数主要为
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
其中first和last为数据的起始地址(迭代器),第三个的comp则是自定义的 比较方式
一般采用三种方法
1 重载小于操作符
对于operator<(a,b)来说,该重载函数的返回值必定是a<b,按照我们前面说的,如果返回值为true,那么就把a放在b前面,也就是说,如果a<b,那么a在排序后序列中是在b前面的,而这一点恰好印证了sort函数的默认排序方式为升序。为了更好的理解这一点,我们来用另一种方式来重载小于号:(重载的方式有多种,可见)
struct stu
{
string name;
int num;
int age;
bool operator<(const stu &p)const
{
return age<p.age;
}
}S[5];
int main(int argc, char *argv[])
{
S[0]={"aa",1,10};
S[1]={"bb",2,9};
S[2]={"cc",3,8};
S[3]={"dd",4,7};
S[4]={"ee",5,6};
sort(S,S+5);
for(auto s:S)
cout<<s.name<<" ";
return 0;
}
在这段程序中,小于号重载为比较两个结构体的成员变量(age)的大小,如果第一个参数的age较小,那么就将该结构体变量放在排序序列的前面。
2 自定义cmp函数
struct stu
{
string name;
int num;
int age;
}S[5];
bool cmp(const stu &q,const stu &p)
{
return q.num<p.num;
}
int main(int argc, char *argv[])
{
S[0]={"aa",1,10};
S[1]={"bb",2,9};
S[2]={"cc",3,8};
S[3]={"dd",4,7};
S[4]={"ee",5,6};
sort(S,S+5,cmp);
for(auto s:S)
cout<<s.name<<" ";
return 0;
}
值得注意的是,在同一份类中定义cmp函数,应该在cmp函数前添加static使它变为一个静态函数,不用实例就能调用。
3 自定义仿函数
struct stu
{
string name;
int num;
int age;
}S[5];
struct cmp
{
operator ()(const stu &q,const stu &p)
{
return q.num>p.num;
}
};
int main(int argc, char *argv[])
{
S[0]={"aa",1,10};
S[1]={"bb",2,9};
S[2]={"cc",3,8};
S[3]={"dd",4,7};
S[4]={"ee",5,6};
sort(S,S+5,cmp());
for(auto s:S)
cout<<s.name<<" ";
return 0;
}
这里相当于重载了小括号操作符,是的类也可以添加()像函数一样使用,故称为仿函数。因为此处将较大的放在前面,因为是按照从大到小排序的。sort调用时要加上括号
priority_queue包在头文件为queue中,它的参数主要为
priority_queue<Type, Container, Functional>
其中Type是基础的数据类型,Container是容器类别(相当于是底层队列是用的底层容器),Funcitional是比较的方式。使用基本数据类型是,只需要传入数据类型,就是大顶堆。写priority_queue的比较函数有两种方法
1. 重载小于操作符
struct stu
{
string name;
int num;
int age;
bool operator<(const stu &p)const
{
return age>p.age;
}
}S[5];
int main(int argc, char *argv[])
{
S[0]={"aa",1,10};
S[1]={"bb",2,9};
S[2]={"cc",3,8};
S[3]={"dd",4,7};
S[4]={"ee",5,6};
priority_queue<stu>q;
for(int i=0;i<5;i++)q.push(S[i]);
while(!q.empty())
{
cout<<q.top().name<<" ";
q.pop();
}
return 0;
}
大的数在前面,因此是从大到小排序
2. 自定义仿函数
struct stu
{
string name;
int num;
int age;
}S[5];
struct cmp
{
operator ()(const stu &q,const stu &p)
{
return q.num<p.num;
}
};
int main(int argc, char *argv[])
{
S[0]={"aa",1,10};
S[1]={"bb",2,9};
S[2]={"cc",3,8};
S[3]={"dd",4,7};
S[4]={"ee",5,6};
priority_queue<stu,vector<stu>,cmp >q;
//priority_queue<stu>q;
for(int i=0;i<5;i++)q.push(S[i]);
while(!q.empty())
{
cout<<q.top().name<<" ";
q.pop();
}
return 0;
}
这里的cmp是按num的从小到大进行排列,然后从末尾(优先级最高)开始弹出
leetcode218,天际线问题,使用优先队列
class Solution {
public:
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
vector<vector<int>> ans;
priority_queue<pair<int,int>> maxs;
//优先队列会自动找到最高的值
int i = 0, n = buildings.size();
//此处的n为建筑物的数量
int cur_x, cur_h;
while(i < n||!maxs.empty()){//当i<n或者优先队列不为空时
if(maxs.empty()||i < n&&maxs.top().second >= buildings[i][0]){
//当优先队列为空或者最大高度建筑的右值大于此时建筑的左值,也就是说出现交叉时
cur_x = buildings[i][0];
while(i < n&&cur_x == buildings[i][0]){
maxs.emplace(buildings[i][2], buildings[i][1]);
++i;
}//当有交叉时,左值作为输入
} else {
//当当前的最高建筑与下一个建筑没有交叉时,考虑考当前建筑的落幕,选取他的右值作为输入,并且此时将多余的弹出去。
cur_x = maxs.top().second;
while(!maxs.empty()&&cur_x >= maxs.top().second){
maxs.pop();//将右值在当前最高建筑的右值之前的建筑都弹出队列,因为这些建筑都不会对天际线产生影响
}
}
cur_h = maxs.empty()? 0:maxs.top().first;//为空的时候就代表着上一个建筑群已经全部计算结束。落幕的高度为0
if(ans.empty()||cur_h != ans.back()[1]){
ans.push_back({cur_x, cur_h});
}
}
return ans;
}
};