对在Leetcode刷题过程中遗漏的CPP语法进行补充,内容较为零碎,就先委屈一点挤挤吧😀,可能较多的是C++14/17新特性 ,如若后期深入学习Modern CPP,可能就会删减单拉出去为一章节了,敬请期待!
(I)auto
auto是一个类型占位符 ,它指示编译器自动推导变量的类型 。编译器会根据初始化表达式 (等号右边的值)来确定auto变量的实际类型。
1 2 3 double y=10.0 ;auto y=10.0 ;
1 2 3 4 auto f = 3.14 ; auto s ("hello" ) ; auto z = new auto (9 ); auto x1 = 5 , x2 = 5.0 , x3 = 'r' ;
但是显然,这么简单的类型推导,auto的作用并不大。
auto常用场景
auto的真正作用是在复杂的类型推导 中,例如迭代器 、lambda表达式 等,使程序更清晰易读。
简化复杂类型声明
1 2 3 4 5 std::vector<int > v = {1 , 2 , 3 , 4 , 5 };for (auto it = v.begin (); it != v.end (); ++it) { std::cout << *it << std::endl; }
范围 for 循环
1 2 3 for (auto element : container) { }
Lambda 表达式
1 auto lambda = [](int x, int y) { return x + y; };
Limitations
(II)结构化绑定
结构化绑定 (Structured Bindings)是C++17这是一个非常实用的语法特性 ,它允许我们同时声明多个变量并从一个聚合类型 (如struct、pair 等)中提取其成员 ,使代码更加简洁易读。
1 auto [var1, var2, ...] = 聚合类型;
解构函数
结构化绑定可以非常方便地处理多个返回值 的函数,例如返回tuple或pair的函数。
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> #include <tuple> using namespace std;tuple<int ,int > calculate (int a,int b) { return {a+b,a-b}; }int main () { auto [add,sub]=calculate (3 ,1 ); cout<<add<<endl; cout<<sub<<endl; return 0 ; }
解构结构体(类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> #include <string> using namespace std;struct Product { string name; double price; int stock; }; Product apple={"apple" ,4.1 ,50 };int main () { auto [name,val,stock]=apple; cout<<name<<val<<stock; return 0 ; }
解构数组(静态)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> using namespace std;int main () { int numbers[5 ] = {10 , 20 , 30 , 40 , 50 }; auto [a, b, c, d, e] = numbers; cout << "Array elements: " << a << ", " << b << ", " << c << ", " << d << ", " << e << std::endl; int matrix[2 ][2 ] = {{1 , 2 }, {3 , 4 }}; auto [row1, row2] = matrix; auto [r1c1, r1c2] = row1; auto [r2c1, r2c2] = row2; cout << "Matrix: " << r1c1 << "," << r1c2 << " | " << r2c1 << "," << r2c2 << endl; return 0 ; }
遍历容器+范围for循环
1 2 3 4 5 6 7 8 9 #include <iostream> #include <unordered_map> using namespace std;int main () { unordered_map<int , string> myMap = {{1 , "one" }, {2 , "two" }, {3 , "three" }}; for (const auto & [key, value] : myMap) { cout << key << ": " << value << endl; } }
(III)容器函数
查找最大值、最小值
max_element返回指向容器中最大元素的迭代器
min_element返回指向容器中最小元素的迭代器
minmax_element:返回一个pair容器 ,其中 first 是最小元素的迭代器 ,second 是最大元素的迭代器
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> #include <algorithm> #include <vector> using namespace std;int main () { vector<int > v={1 ,2 ,3 ,4 ,5 }; auto [min_it,max_it]=minmax_element (v.begin (),v.end ()); cout<<*min_it<<endl; cout<<*max_it<<endl; return 0 ; }
⚠️ 使用*解引用迭代器 *max_element和*min_element返回是元素值
判断排序
is_sorted判断容器是否已排序(默认升序 ):若满足*(i+1)>=*i时,判断已排序
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> #include <algorithm> #include <vector> using namespace std;int main () { vector<int > v1={1 ,2 ,3 ,4 ,5 }; vector<int > v2={1 ,3 ,2 ,4 ,5 }; cout<<"v1排序情况:" <<is_sorted (v1. begin (),v1. end ())<<endl; cout<<"v2排序情况:" <<is_sorted (v2. begin (),v2. end ())<<endl; return 0 ; }
重载比较函数
is_sorted提供重载版本 ,可以接受自定义比较函数 (使用lambda expression )
Leetcode 665.非递减数列
1 2 3 4 5 6 7 8 9 10 #include <iostream> #include <algorithm> #include <vector> using namespace std;int main () { vector<int > v={5 ,4 ,3 ,2 ,1 }; bool is_descending=is_sorted (v.begin (),v.end (),[](int a,int b){return a>b;}); cout<<"v是否降序排序:" <<is_descending<<endl; return 0 ; }
(IV)最大公约数、最小公倍数
C++17 新增了 <numeric> 头文件,其中包含了 gcd 和 lcm 函数,用于计算最大公约数和最小公倍数。
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> #include <numeric> using namespace std;int main () { int a = 8 , b = 12 ; int g = gcd (a, b); int l = lcm (a, b); cout << g << endl; cout << l << endl; return 0 ; }
这里考虑到CSP考试中可能只支持C++11,这里再进行一次手动实现:
最大公约数从大到小循环
1 2 3 4 5 6 7 int gcd (int a, int b) { for (int i = min (a, b); i >= 1 ; i--) { if (a % i == 0 && b % i == 0 ) { return i; } } return 1 ;
最大公约数欧几里得算法(辗转相除法)
1 2 3 4 5 6 7 8 int gcd (int a, int b) { while (b != 0 ) { int temp = b; b = a % b; a = temp; } return a; }
1 2 3 4 5 int gcd (int a, int b) { if (b == 0 ) return a; return gcd (b, a % b); }
最小公倍数
通常求得最大公约数后通过公式 实现:
$$ LCM(a, b) = \frac{(a × b)}{GCD(a, b)}$$
1 2 3 int lcm (int a, int b) { return (a / gcd (a, b)) * b; }
map容器
手动转换为降序
1 map<int ,int ,greater<int >> ans;
原题链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution {public : vector<string> findRelativeRanks (vector<int >& score) { int n=score.size (); vector<string> ans (n) ; map<int ,int ,greater<int >> order; for (int i=0 ;i<n;i++){ order[score[i]]=i; } auto it=order.begin (); for (int i=0 ;i<n;i++){ if (i==0 ){ ans[(*it).second]="Gold Medal" ; } else if (i==1 ){ ans[(*it).second]="Silver Medal" ; } else if (i==2 ){ ans[(*it).second]="Bronze Medal" ; } else ans[(*it).second]=to_string (i+1 ); it++; } return ans; } };
排序字符串
1 2 3 4 5 6 7 8 9 10 #include <iostream> #include <algorithm> #include <string> using namespace std;int main () { string str = "badfikhfgoia" ; sort (str.begin (), str.end ()); cout << str << endl; return 0 ; }
判断两个字符串是否为字母异位词,效果与下面函数相同:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 bool compare (string str1,string str2) { vector<int > freq (26 ) ; for (char ch:str1){ freq[ch-'a' ]++; } for (char ch:str2){ freq[ch-'a' ]--; } for (int i=0 ;i<26 ;i++){ if (freq[i]!=0 ) return false ; } return true ; } }
<numeric>
数组求和
Leetcode 3422.统计元素和差值为偶数的分区方案
1 2 3 4 5 6 7 8 9 class Solution {public : int countPartitions (vector<int >& nums) { long long sum=accumulate (nums.begin (),nums.end (),0LL ); int n=nums.size (); if (sum%2 ==0 ) return n-1 ; else return 0 ; } };
1 accumulate (first,last,init,binary_op);
用于计算序列中所有元素的累积和
first, last:迭代器范围
init:初始值(必须正确指定类型)
binary_op:二元操作函数(可选,默认是加法)
注意使用 long long 避免溢出
1 2 vector<int > large_nums = {1000000000 , 1000000000 , 1000000000 };long long sum = accumulate (large_nums.begin (), large_nums.end (), 0LL );