其实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 = #
学校也从没教过在变量声明时使用取地址符号,当然自己见过很多次,但也没有下手去查,今天就一口气弄明白了。
首先下结论,关于指针和引用
- 他们都是地址
- 指针可以为空,引用不可以为空,引用在声明之时就必须与已有的变量绑定
用一句话总结** “引用就是用常量指针实现的” **
参考资料
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;
}