算法-排序-匿名函数

一、知识点介绍

匿名函数

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. 总结

最后一题的逻辑好绕,看题目看了好久,也写了好久。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值