一、知识点介绍
匿名函数
1. 什么是匿名函数
C++中的匿名函数,是在句中定义和声明一个临时函数,仅在调用时才会创建函数对象,无需在头文件中声明。
2. 匿名函数形式
[capture](parameters) -> return-type{body}
--------------------------------------------------
[捕获列表](参数列表)->返回类型-{函数主体}
capture: 捕获列表
- [] //捕获列表为空。在函数内无法使用外部变量
- [a] //捕获列表为按值传递形式。在函数内仅能使用传递的变量值,无法改变变量。值在匿名数生成时已经被确定,后续修改不会影响函数内的变量值。
- [&a] //按引用传递。可改变变量。
return-type: 返回类型
一般情况下编译器可以推断出返回类型,可以用auto而不指定返回类型。但是有多各return语句时需要指定返回类型。
3. 例子
1. 直接写在main函数中
#include<iostream>
using namespace std;
int main(){
int x=1,y=2,z=0;
auto add = [&z](auto x,auto y){z=x+y;return z;};
auto res = add(x,y);
cout<<res<<z<<endl;
}
2. 和sort()一起连用
一维数组降序排序为:
vector<int> costs;
sort(costs.begin(), costs.end(), [&](const int& a, const int& b) {
return a > b
});
二、练习题目
(1) 数组中两元素的最大乘积
(2) 按照频率将数组升序排序
(3) 有序数组中出现次数超过25%的元素
(4) 寻找右区间
三、算法思路
1. 数组中两元素的最大乘积
(1)这道题考察了C++函数库中的sort():https://www.cplusplus.com/reference/algorithm/sort/?kw=sort
class Solution {
public:
int maxProduct(vector<int>& nums) {
sort(nums.begin(), nums.end());
return (nums[nums.size()-1]-1)* (nums[nums.size()-2]-1);
}
};
2. 按照频率将数组升序排序
(1) 因为数组元素的范围是:[-100, 100],要处理负数,方法就是都加100,并且设置哈希表的的大小超过两百,再在哈希表中存入每个元素出现的次数。
(2)sort()函数的默认是按照升序排序,这道题需要按照数字出现的频率升序排序;如果频率相等,需要按照数值的大小降序排序,所以要重写sort()函数。
class Solution {
#define base 100
public:
vector<int> frequencySort(vector<int>& nums) {
int hash[210];
memset(hash, 0, sizeof(hash));
int i;
for(i = 0; i < nums.size(); ++i) {
++hash[nums[i] + base];
}
sort(nums.begin(), nums.end(), [&](const int& a, const int& b) {
if(hash[a + base] != hash[b + base]) {
return hash[a + base] < hash[b + base];
}
return a > b;
});
return nums;
}
};
3. 有序数组中出现次数超过25%的元素
(1) 遍历整个数组统一每个元素出现的次数,如果次数大于25%的话就返回这个整数并且break。
(2)需要注意的点就是能把除法换成乘法就尽量换成乘法。
class Solution {
public:
int findSpecialInteger(vector<int>& arr) {
int cnt = 1;
int i;
for(i = 1; i < arr.size(); ++i) {
if(arr[i] == arr[i-1]) {
cnt++;
} else {
cnt = 1;
}
//cnt/n = 25/100
//cnt * 100 = 25 * n
if(cnt * 100 > 25 * arr.size()) {
return arr[i];
}
}
return arr[0];
}
};
4. 寻找右区间
(1) 这道题的题目有点难懂:
1.start <= end;
2.本区间的end <= 下一个区间的start ;
3. 如果第二步成立的话,把下一个区间start的下标值存到答案数组中。
(2) 所以根据题目意思,初始化的操作有:1. 需要创建一个跟题目数组一模一样的二维数组,暂且叫做copy;2. 需要创建一个存放答案的hash表,hash表的大小和intervals的大小一样大,并且初始化每个值为-1;
(3) copy数组和intervals数组都要在每一组区间当中添加下标值;
(4) 对copy数组的每一组区间的start的数值进行升序排序;再对intervals数组的每一组区间的end的数值进行升序排序
(5) 遍历判断每个区间的end的值是不是小于等于某区间的start的值;如果有就把那个start的值的区间的下标值存到答案数组中。
class Solution {
public:
vector<int> findRightInterval(vector<vector<int>>& intervals) {
int i,j = 0;
vector<int> ans;
vector<vector<int>> copy;
for(i = 0; i < intervals.size(); ++i) {
copy.push_back(intervals[i]);
copy.back().push_back(i);
}
for(i = 0; i < intervals.size(); ++i) {
intervals[i].push_back(i);
ans.push_back(-1);
}
//sort end
sort(intervals.begin(), intervals.end(), [&](const vector<int>& a, const vector<int>& b){
return a[1] < b[1];
});
//sort start
sort(copy.begin(), copy.end(), [&](const vector<int>& a, const vector<int>& b){
return a[0] < b[0];
});
for(i = 0; i < intervals.size(); ++i) {
int preidx = intervals[i][2];
for(j = 0; j < copy.size(); ++j) {
int prejdx = copy[j][2];
if(intervals[i][1] <= copy[j][0]) {
ans[preidx] = prejdx;
break;
}
}
}
return ans;
}
};
5. 总结
最后一题的逻辑好绕,看题目看了好久,也写了好久。。。。