since 2019-6-29
经典流传
C++
-
string中的=是复制一份新的字符串,不是共享同一个字符串。
-
初始化priority_queue
const auto cmp = [](pair<int, int> &a, pair<int, int> &b) { return a.first > b.first; }; priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);
-
通过空格拆分字符串
string str = "dog cat cat dog"; istringstream in(str); vector<string> v; string t; while (in >> t) { v.push_back(t); }
- 以下用两个例子来说明std::move的用法. 原lvalue值被moved from之后值被转移,所以为空字符串. 摘录自cppreference
- unordered_map<string, map<int, string» s_;
- auto it = m->second.upper_bound(timestamp); if (it == begin(m->second)) return “”;
-
写dp的时候,两重循环,第一层循环控制距离,第二层循环控制行号
- unordered_set
unordered_set<string> dict(wordDict.cbegin(), wordDict.cend()); //mark
- random
#define random(x) (rand()%x) 返回一个[0,x)之间的整数 rand() 返回一个0至RAND_MAX (stdlib.h) 2147483647间的随机数
- vector
vector<vector<int>> _m; _m = vector<vector<int>>(n, vector<int>(n, INT_MIN)); //mark
- 一点点
sort(ins.begin(), ins.end(), [](vector<int> a, vector<int> b){return a[0] < b[0];} // unique函数返回去重后最后一个元素迭代器 // Trie这么写 vector<bool> passed(n, false) stringstream inplace_merge(begin, mid, right);
- C++命名规范 [google]
- 函数命名, 变量命名, 文件命名要有描述性;
- 文件名要全部小写, 可以包含下划线 () 或连字符 (-), 依照项目的约定. 如果没有约定, 那么 “” 更好.
- 类型名称的每个单词首字母均大写, 不包含下划线: MyExcitingClass, MyExcitingEnum.
- 变量 (包括函数参数) 和数据成员名一律小写, 单词之间用下划线连接. 类的成员变量以下划线结尾, 但结构体的就不用, 如: a_local_variable, a_struct_data_member, a_class_data_member_.
- 不管是静态的还是非静态的, 类数据成员都可以和普通变量一样, 但要接下划线。 string table_name_; // 好 - 后加下划线. string tablename_; // 好.static Pool
* pool_; // 好. - 结构体变量
- 常量命名 const int kDaysInAWeek = 7; 声明为 constexpr 或 const 的变量, 或在程序运行期间其值始终保持不变的, 命名时以 “k” 开头, 大小写混合. 例如:
- 函数命名。常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable().
- 7.7. 命名空间命名
class Solution { public: int KthSmallest(vector<vector<int>>& matrix, int k) { int n = matrix.size() - 1; int le = matrix[0][0], ri = matrix[n][n]; while (le < ri) { int mid = le + (ri - le) / 2; int lt_count = 0; for (int i = 0; i <= n; i++) { lt_count += upper_bound(matrix[i].begin(), matrix[i].end(), mid) - matrix[i].begin(); } if (lt_count < k) { le = mid + 1; } else { ri = mid; } } return le; } };
- 常用C++ code 在线编程
auto it = lower_bound(res.begin(), res.end(), i); if (it == res.end()) { #define A(i) nums[(1+2*(i)) % (n|1)] // 天哪,神来之笔,,,,
```C++ class disjoint_set { vector
v; int sz; public: disjoint_set(int n) { makeset(n); } void makeset(int n) { v.resize(n); // std::iota :用顺序递增的值赋值指定范围内的元素 。 iota(v.begin(), v.end(), 0); sz = n; } int find(int i) { if (i != v[i]) v[i] = find(v[i]); return v[i]; } void join(int i, int j) { int ri = find(i), rj = find(j); if (ri != rj) { v[ri] = rj; sz--; } } int size() { return sz; } };
- C++格式
- 若用引用捕获, 在变量名和 & 之间不留空格.auto add_to_x = [&x](int n) { x += n; };
- if (condition) { // 好 - IF 和 { 都与空格紧邻.
- :左边 ;左边 (右边 )左边
- ./-> 操作符前后不留空格, */& 不要前后都留, 一个就可, 靠左靠右依各人喜好;
``` C++
if (b) { // if 条件语句和循环语句关键字后均有空格.
} else { // else 前后有空格.
}
while (test) {} // 圆括号内部不紧邻空格.
for (int i = 0; i < 5; ++i) {
switch (i) {
case 1: // switch case 的冒号前无空格.
...
case 2: break; // 如果冒号有代码, 加个空格.
x = 0; // 赋值运算符前后总是有空格.
// 其它二元操作符也前后恒有空格, 不过对于表达式的子式可以不加空格.
// 圆括号内部没有紧邻空格.
v = w * x + y / z;
v = w * (x + z);
// 在参数和一元操作符之间不加空格.
x = -5;
++x;
if (x && !y)
// 尖括号(< and >) 不与空格紧邻, < 前没有空格, > 和 ( 之间也没有.
vector<string> x;
y = static_cast<char*>(x);
// 在类型与指针操作符之间留空格也可以, 但要保持一致.
vector<char *> x;
- C++ 常用容器
// 无序集合 unordered_set<string> d(wordList.begin(), wordList.end()); d.erase(head); // 双端队列 deque<string> dq; string head = dq.front(); dq.pop_front();
- 并查集 https://www.jianshu.com/p/def7767982ac
private int count; private int[] parents; //初始化并查集 public void initUnionFind(int m, int n, char[][] grid){ parents = new int[m*n]; for(int i=0; i<m; i++){ for(int j=0; j<n; j++){ if(grid[i][j] == '1'){ count++; } parents[i*n+j] = i*n+j; } } } public int find(int idx){ while(idx != parents[idx]){ //在查找的过程中压缩路径,减少查找的次数 parents[idx] = parents[parents[idx]]; idx = parents[idx]; } return idx; } public void union(int p, int q){ int pRoot = find(p); int qRoot = find(q); //两个元素的根不同,则合并 if(pRoot != qRoot){ parents[qRoot] = pRoot; count--; } } public boolean isConnected(int p, int q){ int pRoot = find(p); int qRoot = find(q); //两点不连通 if(pRoot != qRoot){ return false; } return false; }
```位运算 int diff = accumulate(nums.begin(), nums.end(), 0, bit_xor
()); diff &= -diff;
- sort 内部写一个比较器
```C++
sort(numbers.begin(),numbers.end(),[](const int s1,const int s2){
return to_string(s1)+to_string(s2) < to_string(s2) + to_string(s1);
});
or
struct Comp {
bool operator()(const pair<int, string>& lhs, const pair<int, string>& rhs) const {
if (lhs.first != rhs.first)
return lhs.first < rhs.first;
return lhs.second > rhs.second;
}
};
priority_queue<pair<int, string>, vector<pair<int, string>>, Comp> Q;
- C++ 分割字符串 变为stringstream
stringstream ss(path); while(getline(ss,tmp,'/')) { if (tmp == "" or tmp == ".") continue;
- C++ make_pair,queue.front().first,return {},pair<TreeNode* ,int>
if(root == NULL) return {}; queue<pair<TreeNode *, int>> q; q.push(make_pair(root,0)); TreeNode * t = q.front().first; q.pop(); res.push_back({t->val}); res[level].insert(res[level].begin(),t->val);
// - C++ 实现自定义字符串比较函数
static bool sortCom(const string &a, const string &b) {
return (a+b) > (b+a);
}
sort(arr.begin(), arr.end(), sortCom);
// vector , deque, pair 相关
deque<pair<int, int>> queue;
queue.push_back(make_pair(i,j));
int curi = queue.front().first, curj = queue.front().second;
queue.pop_front();
// 按照vector<pair<int, int>> 中两个数的比值排序
typedef pair<int, int> pii;
bool piisort(pii a, pii b) {
// a.first / a.second > b.first / b.second
return a.first * (ll)b.second > a.second * (ll)b.first;
}
- C++ 实现tire树
class TireNode { public: //注意这里应该是public: char value; bool isend; vector<TireNode *> next; TireNode(): value(' '), isend(false){}; //注意这里使用初始化表来初始化对象 TireNode(char v): value(v), isend(false){}; TireNode* subNode(char c) { if(!next.empty()){ for(auto child: next) { if(child->value == c) { return child; } } } return nullptr; } ~TireNode(){ for(auto child: next) delete(child); } }; class Trie { private: TireNode* root; public: /** Initialize your data structure here. */ Trie() { root = new TireNode(); } /** Inserts a word into the trie. */ void insert(string word) { TireNode* cur = root; int i = 0; for( ; i < word.size(); i++) { TireNode* curNext = cur->subNode(word[i]); if (curNext) { cur = curNext; } else { break; } } if (i >= word.size()) { cur->isend = true; } else { for ( ; i < word.size(); i++) { TireNode* newNode = new TireNode(word[i]); cur->next.push_back(newNode); cur = cur->subNode(word[i]); } } cur->isend = true; } /** Returns if the word is in the trie. */ bool search(string word) { TireNode* cur = root; for (int i = 0; i < word.size(); i++) { TireNode* curNext = cur->subNode(word[i]); if (curNext) { cur = curNext; } else { return false; } } return cur->isend; } /** Returns if there is any word in the trie that starts with the given prefix. */ bool startsWith(string word) { TireNode* cur = root; for (int i = 0; i < word.size(); i++) { TireNode* curNext = cur->subNode(word[i]); if (curNext) { cur = curNext; } else { return false; } } return true; } }; /** * Your Trie object will be instantiated and called as such: * Trie* obj = new Trie(); * obj->insert(word); * bool param_2 = obj->search(word); * bool param_3 = obj->startsWith(prefix); */