竞赛中的C++小方法汇总

其实c++中有许多小方法,但是csdn就像一个巨大的垃圾库,你很容易搜到一些很垃圾的博客或代码,因此在这里做一个自用的总结。

1 c++自动类型循环

vector<int> arr;
for (const auto& i : arr) {
	cout<<i;
}

2 c++对vector、数组排序。向量插入数据

vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
    sort(people.begin(), people.end(), [](const vector<int>& u, const vector<int>& v) {
        return u[0] > v[0] || (u[0] == v[0] && u[1] < v[1]);
    });
    vector<vector<int>> ans;
    for (const vector<int>& person: people) {
    	// vector.insert(pos, target) 第一个参数是位置begin()+长度,第二个参数target是内容。
        ans.insert(ans.begin() + person[1], person);
    }
    return ans;
}

上面是是比较新的写法,接下来看看传统写法:

// 必须是静态函数,但是在using namespace std;下不用。
static bool cmp(vector<int> &a, vector<int> &b) {
	return a[0] < b[0] || (a[1] == b[1] && a[1] > b[1]);
}

int main () {
	...
	sort(a.begin(), a.end(), cmp);
	sort(a, a+length, cmp);
}

3 C++ 结构体构造函数

struct node
{
    int x,y,state,step;
    int hasRock;
    node(int a, int b, int c, int d, int e):x(a), y(b), state(c), step(d), hasRock(f){}
}

node start = node(0,0,0,0,0);

4 引用和指针

我之前一直看不懂如下的代码:

int dfs(int &a) {
	pass
}

int main () {
	int num = 10;
	dfs(num);
}

因为只用大一短暂地学了一下c语言,我对指针和&这个符号的理解一直是这样的:
要么这样定义一个指针,或者在函数中接收一个指针

int* a;

int func (int *num) {}

要么用取地址符&,把变量的地址赋值给一个指针

int num = 10;
int* p = &num;

学校也从没教过在变量声明时使用取地址符号,当然自己见过很多次,但也没有下手去查,今天就一口气弄明白了。

首先下结论,关于指针和引用

  • 他们都是地址
  • 指针可以为空,引用不可以为空,引用在声明之时就必须与已有的变量绑定

用一句话总结** “引用就是用常量指针实现的” **
参考资料

5 定义长度为n,初始值都是num的vector

vector<int> dp(n, num);

6 对vector、数组取最大最小值

int ans = *max_element(dp.begin(), dp.end());
int ans = *max_element(dp, dp+length);

7 c++中的pair

pair的场景和用法,leetcode 164. 最大间距

class Solution {
public:
    int maximumGap(vector<int>& nums) {
        int n = nums.size();
        if (n < 2) {
            return 0;
        }
        int minVal = *min_element(nums.begin(), nums.end());
        int maxVal = *max_element(nums.begin(), nums.end());
        int d = max(1, (maxVal - minVal) / (n - 1));
        int bucketSize = (maxVal - minVal) / d + 1;

        vector<pair<int, int>> bucket(bucketSize, {-1, -1});  // 存储 (桶内最小值,桶内最大值) 对,(-1, -1) 表示该桶是空的
        for (int i = 0; i < n; i++) {
            int idx = (nums[i] - minVal) / d;
            if (bucket[idx].first == -1) {
                bucket[idx].first = bucket[idx].second = nums[i];
            } else {
                bucket[idx].first = min(bucket[idx].first, nums[i]);
                bucket[idx].second = max(bucket[idx].second, nums[i]);
            }
        }

        int ret = 0;
        int prev = -1;
        for (int i = 0; i < bucketSize; i++) {
            if (bucket[i].first == -1) continue;
            if (prev != -1) {
                ret = max(ret, bucket[i].first - bucket[prev].second);
            }
            prev = i;
        }
        return ret;
    }
};

8 创建一个自定义排序的优先队列

规则:先搞清楚你的优先队列里存的数据类型,这里是一个pair<int, int>记为T,那么声明优先队列的时候,需要三个参数,第一个就是类型T,第二个就是vector<T>,第三个是cmp的类型,这里可以用c++中自动类型判断来识别。

注意的是,优先队列是反过来的,如果你想从大到小排序,申明cmp函数的时候,就是从小到大。

auto cmp = [](const pair<int, int> &a, const pair<int, int> &b) {
	return a.second < b.second;
};
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q{cmp};

9 声明一个全是0的二维数组

vector<vector<int>> graph(rows, vector<int>(columns, [0]));

10 使用 emplace_back 代替 push_back

理论上来讲,emplace_back 的性能是要比 push_back 好。

11 哈希表 unordered_map 与 红黑树 map

还在我大学期间参见ACM竞赛的时候,还没有或是不知道 unordered_map 这个东西。

说说用法与区别

  • map 内部实现是红黑树,因此插入即排序,如果在有需要顺序的情况下,用map是极好的。
  • unordered_map 内部实现是哈希表,正如它的名字一样,是没有顺序的,在查询时速度非常快,但是会占用更多的空间。

哈希表在使用时直接当数组用就可以了,而且会给予该类型的默认值,以及如何迭代等具体看代码。

例题:LeetCode .554 砖墙 https://leetcode-cn.com/problems/brick-wall/

int leastBricks(vector<vector<int>>& wall) {
    unordered_map<int ,int> hs;
    int maxWidth = 0;
    for (int &width : wall[0]) {
        maxWidth += width;
    }
    for (vector<int>& row : wall) {
        int prefixSum = 0;
        for (int& width : row) {
            prefixSum += width;
            hs[prefixSum] += 1;
        }
    }
    int maxValue = 0;
    for (auto& [key, value] : hs) {
        if (key != maxWidth) {
            maxValue = max(maxValue, value);
        }
    }
    return wall.size() - maxValue;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值