description和keywords都是给爬虫看的
map myMap键值对,键唯一,按照键的大小自动排序
1 2 3 4 5 6 7 8 9 10 11 12 13 myMap.insert (make_pair (1 , 100 )) #make_pair打包键值对 myMap[2 ] = 200 ; myMap.insert ({{3 , 300 }, {4 , 400 }}); auto it = myMap.find (3 );if (it != myMap.end ()) { a= it->first; b= it->second ; } else { } myMap.erase (1 );
str.size()获取列表长度
string定义字符串
unordered_map:适合对元素顺序没有要求,且需要快速访问的场景,尤其是在元素数量较多且频繁进行查找、插入和删除操作时。
.push_back(),在vector后面添加元素
vector> ans 多维数组
unordered_set 只允许存储唯一的元素,列表去重
1 2 3 4 for (int &num:nums){ st.count (num-1 ) }
哈希表:
数组,哈希范围可控,数值较小的情况
,set数值很大
,map键值对
三种set
uordered_set自动去重
KMP算法
那么什么是前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。
所以字符串a的最长相等前后缀为0。 字符串aa的最长相等前后缀为1。 字符串aaa的最长相等前后缀为2。 等等…..。
const string&str来代替string str直接传参,减少内存开销,避免完整拷贝,占用额外空间。
二分查找 无敌公式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int searchInsert(vector<int>& nums, int target) { int left = 0; int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right] while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <= int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2 if (nums[middle] > target) { right = middle - 1; // target 在左区间,所以[left, middle - 1] } else if (nums[middle] < target) { left = middle + 1; // target 在右区间,所以[middle + 1, right] } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } } // 未找到目标值 return left; }
(right - left) >>1相当于(right - left) / 2
left是插入位置,注意在多维搜索的时候要在索引不为0的情况下取前一行
注意越界检查,移动查重的时候可以左边先移动再右边先移动
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 while(a>=0&&a<nums.size()&&nums[a]==target||b>=0&&b<nums.size()&&nums[b]==target) { if(a>=0&&a<nums.size()&&nums[a]==target) { a--; } if(b>=0&&b<nums.size()&&nums[b]==target) { b++; } } 改成 // 专门向左找边界 while(a >= 0 && nums[a] == target) { a--; } // 专门向右找边界 while(b < nums.size() && nums[b] == target) { b++; } result[0] = a + 1; result[1] = b - 1; return result;
其余情况
注意等号的位置和情况的分类
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 27 28 29 30 31 class Solution { public: int search(vector<int>& nums, int target) { //折叠二分查找 int left = 0; int right = nums.size()-1; while(left<=right) { int mid = (left+right)/2; if(nums[mid]==target)return mid; if(nums[0]>nums[mid]) { if(target>nums[mid]&&target<=nums[nums.size()-1]) { left = mid+1; }else{ right = mid-1; } }else{ if(target>=nums[0]&&target<nums[mid]) { right = mid-1; }else{ left = mid+1; } } } return -1; } };
非对称更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int findMin(vector<int>& nums) { int left =0; int right=nums.size()-1; if(nums[left]<nums[right])return nums[left]; while(left<right) { int mid = (left+right)/2; if(nums[left]<=nums[mid]&&nums[right]>=nums[mid])break; if(nums[mid]>=nums[left]) { left = mid+1; }else{ right =mid; } } return min(nums[left],nums[right]); }
栈和队列 栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。
所以STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。
我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构
deque 是双端队列
1 std::stack<int , std::vector<int > > third;
队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。
1 std::queue<int , std::list<int >> third;
队列的底层容器不能用vector
vector的pop_front()是O(n)(需要移动所有元素),而deque和list的pop_front()是O(1)
栈操作
stackst
函数
功能
返回类型
时间复杂度
push(const T& val)
元素入栈
void
O(1)
pop()
移除栈顶元素
void
O(1)
top()
返回栈顶元素(不删除)
T&(可修改)或 const T&(只读)
O(1)
empty()
判断栈是否为空
bool(true 为空)
O(1)
size()
返回栈中元素数量
size_t(无符号整数)
O(1)
队列操作
queue que
操作
函数
返回类型
注意事项
入队
push() / emplace()
void
emplace 更高效
出队
pop()
void
需先调用 front()
访问队首
front()
T& 或 const T&
可修改或只读
访问队尾
back()
T& 或 const T&
可修改或只读
判空
empty()
bool
true 表示空
大小
size()
size_t
元素数量
字符串拼接可以用pushback也可以直接+;
1 2 3 4 5 6 string result; result+=st.top (); reverse (result.begin (),result.end ());
switch不支持string判别
哈希表转vector
vector> sortedPairs(hashMap.begin(), hashMap.end());
sort按照容器自定义排序 []中是引用外部变量,也是三种传参方式
1 2 3 4 5 6 7 std::sort ( sortedPairs.begin (), sortedPairs.end (), [](const auto & a, const auto & b) { return a.second < b.second; } );
1 2 3 4 5 6 7 8 9 std::sort (nums.begin (), nums.end (), [threshold](int a, int b) { bool a_gt = (a > threshold); bool b_gt = (b > threshold); if (a_gt != b_gt) { return a_gt > b_gt; } else { return a < b; } });
multimap只能用.insert传参,因为可以包含重复键值对,但是multimap是有序的默认升序,都是按照键来排序
传参直接用{,}
1 2 3 4 std::multimap<int , std::string> sortedMap; for (const auto & pair : hashMap) { sortedMap.insert ({pair.second, pair.first}); }
multimap实现降值排序,map同样适用
1 2 3 4 5 6 7 std::multimap<int , std::string, std::greater<int >> mmap = { {3 , "Banana" }, {1 , "Apple" }, {2 , "Avocado" }, {1 , "Apricot" } };
判断multimap是否有重复
哈希表转数组,注意数组变量的前后要用->来引用,
注意从后向前遍历,可以用rbegin()和rend()
1 2 3 4 5 6 7 vector<pair<int , int >> sortedPairs (sortmap.begin (), sortmap.end ()); vector<int >result; for (auto it =sortedPairs.rbegin ();it<sortedPairs.rbegin ()+k;it++) { result.push_back (it->second); }
快速排序
通过一趟排序将待排数据分割成独立的两部分,其中一部分的所有元素均比另一部分小,然后递归地对这两部分继续排序,最终完成整个序列的排序
快速排序
O(n log n)
不稳定
O(log n)
通用、数据量大
归并排序
O(n log n)
稳定
O(n)
需要稳定排序或外部排序
大顶堆和小顶堆
优先级队列
其实就是一个披着队列外衣的堆 ,因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。
堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。
比较规则的作用 返回值决定顺序
return a.first > b.first的布尔结果会告诉priority_queue
如果为 true:a 应该排在 b 的后面(即 a 的优先级更低)。
如果为 false:a 应该排在 b 的前面或保持原顺序(即 a 的优先级更高或相等)。
优先级队列的操作
操作
正确性
说明
pri_que.push(it)
❌ 错误
类型不匹配,且可能引发悬空指针。
pri_que.push(*it)
✅ 可用
隐式转换 pair<const int, int> 为 pair<int, int>。
pri_que.push({it->first, it->second})
✅ 推荐
显式构造 pair<int, int>,明确类型转换,避免潜在问题。
auto it = map.begin()
it的类型是std::unordered_map::iterator
特性
迭代器 (std::unordered_map::iterator)
指针 (T*)
本质
类对象(可能包含复杂逻辑)
内存地址的数值
解引用 *it
返回 std::pair<const int, int>&
返回指向的对象
成员访问 it->
访问键值对的成员(如 it->first)
访问结构体/类的成员
失效风险
容器修改(如插入/删除)可能导致迭代器失效
仅当内存释放后失效
算术运算
不支持 it + 1(无序容器)
支持指针算术(如 ptr + 1)
关于用->second访问还是用.second来访问
,如果是引用,则用->,是成员的话用.
双端队列常用函数deque
函数
作用
时间复杂度
front()
返回首元素引用
O(1)
back()
返回尾元素引用
O(1)
operator[]
通过下标访问元素(无边界检查)
O(1)
at(index)
通过下标访问元素(有边界检查)
O(1)
push_front(val)
头部插入元素
O(1)
push_back(val)
尾部插入元素
O(1)
pop_front()
删除头部元素
O(1)
pop_back()
删除尾部元素
O(1)
insert(pos, val)
在指定位置插入元素
O(n)
erase(pos)
删除指定位置元素
O(n)
size()
返回当前元素数量
empty()
判断是否为空
resize(n)
调整容器大小
clear()
清空所有元素
二叉树 堆是一个完全二叉树
二叉树的存储方式:
链式存储:指针
顺序存储:数组
数组:2i+1是左子,2 i+2是右子
二叉树的节点定义
1 2 3 4 5 6 7 8 9 struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode (int a):val (a),left (NULL ),right (NULL ){} } TreeNode* newtree = new TreeNode (1 );
二叉树真勾八抽象呀,老子今天下午一定给你啃下来
递归遍历 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 void traversal (TreeNode * cur,vector<int >& vec) { if (cur==NULL )return ; vec.push_back (cur->val); traversal (cur->left,vec); traversal (cur->right,vec); } void traversal (TreeNode * cur,vector<int >& vec) { if (cur==NULL )return ; traversal (cur->left,vec); vec.push_back (cur->val); traversal (cur->right,vec); } void traversal (TreeNode * cur,vector<int >& vec) { if (cur==NULL )return ; traversal (cur->left,vec); traversal (cur->right,vec); vec.push_back (cur->val); }
二叉树递归遍历(三种顺序:中左右,左中右,左右中)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void traversal (TreeNode* cur,vector<int >& vec) { if (cur == NULL ) return ; vec.push_back (cur->val); traversal (cur->left, vec); traversal (cur->right, vec); } void traversal (TreeNode* cur, vector<int >& vec) { if (cur == NULL ) return ; traversal (cur->left, vec); vec.push_back (cur->val); traversal (cur->right, vec); } void traversal (TreeNode* cur, vector<int >& vec) { if (cur == NULL ) return ; traversal (cur->left, vec); traversal (cur->right, vec); vec.push_back (cur->val); }
二叉树的迭代遍历 递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中 ,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 vector<int > pretraversal (TreeNode* root) { stack<TreeNode*>st; vector<int >result; TreeNode* cur = root; st.push (root) while (!st.empty ()) { cur = st.top (); st.pop (); result.push_back (cur->val) if (cur->right!=NULL )st.push (cur->right); if (cur->left!=NULL )st.push (cur->left); } return result } vector<int > midtraversal (TreeNode* root){ stack<TreeNode*>st; vector<int >result; TreeNode* cur = root; while (!st.empty ()||cur!=NULL ) { if (cur!=NULL ) { st.push (cur); cur = cur->left; }else { cur = st.top (); result.push_back (cur->val); st.pop (); cur=cur->right; } } return result; } vector<int > pastraversal (TreeNode* root) { stack<TreeNode*>st; vector<int >result; TreeNode* cur = root; st.push (root) while (!st.empty ()) { cur = st.top (); st.pop (); result.push_back (cur->val) if (cur->left!=NULL )st.push (cur->left); if (cur->right!=NULL )st.push (cur->right); } reverse (result.begin (),result.end ()); return result; }
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 vector<int > preordertraversal (TreeNode* root) { vector<int >result; if (cur==NULL )return ; stack<TreeNode*>st; st.push (cur); while (!st.empty ()) { TreeNode* cur = st.top (); st.pop (); result.push_back (cur->val); if (cur->right!=NULL )st.push (cur->right); if (cur->left!=NULL )st.push (cur->left); } return result } vector<int > inordertraversal (TreeNode* root){ vector<int >result; TreeNode* cur = root; if (cur==NULL )return ; stack<TreeNode*>st; while (!st.empty ()||cur!=NULL ) { if (cur!=NULL ) { st.push (cur); cur = cur->left; }else { cur = st.top (); st.pop (); result.push_back (cur->val); cur = cur->right; } } } vector<int > postordertraversal (TreeNode* root) { vector<int >result; TreeNode* cur = root; if (cur==NULL )return ; stack<TreeNode*>st; st.push (cur); while (!st.empty ()) { cur = st.pop (); result.push_back (cur->val); if (cur->left!=NULL )st.push (cur->left); if (cur->right!=NULL )st.push (cur->right); } reverse (result.begin (), result.end ()); return result }
迭代统一遍历 无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况 两种标记法 空指针标记法
中序遍历 空指针标记法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 vector<int > midtraversal (TreeNode* root) { vector<int >result; TreeNode* cur= root; stack<TreeNode*>st; if (root != NULL ) st.push (root); while (!st.empty ()) { cur = st.top (); st.pop (); if (cur!=NULL ) { if (cur->right)st.push (cur->right); st.push (cur); st.push (NULL ); if (cur->left)st.push (cur->left); }else { cur = st.top (); result.push_back (cur->val); st.pop (); } } return result; }
boolean标记法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 vector<int > midtraversal (TreeNode* root) { vector<int >result; stack<pair<TreeNode*,bool >>st; if (root!=nullptr )st.push (make_pair (root,false )); while (!st.empty ()) { auto curnode = st.top ().first; auto visited = st.top ().second; st.pop (); if (visited) { result.push_back (curnode->val); continue ; } if (curnode->right)st.push (make_pair (curnode->right,false )); st.push (make_pair (curnodet,true )); if (curnode->left)st.push (make_pair (curnode->left,false )); } } return result; }
前序遍历 空指针标记法:
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 vector<int > pretraversal (TreeNode* root) { vector<int >result; TreeNode* cur= root; stack<TreeNode*>st; if (root != NULL ) st.push (root); while (!st.empty ()) { cur = st.top (); if (cur!=NULL ) { st.pop (); if (cur->right)st.push (cur->right); if (cur->left)st.push (cur->left); st.push (cur); st.push (NULL ); }else { st.pop (); cur = st.top (); result.push_back (cur->val); st.pop (); } } return result; }
boolean标记法
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 vector<int > pretraversal (TreeNode* root) { vector<int >result; stack<pair<TreeNode*,bool >>st; if (root!=nullptr )st.push (make_pair (root,false )); while (!st.empty ()) { auto curnode = st.top ().first; auto visited = st.top ().second; st.pop (); if (visited) { result.push_back (curnode->val); continue ; } if (curnode->right)st.push (make_pair (curnode->right,false )); if (curnode->left)st.push (make_pair (curnode->left,false )); st.push (make_pair (curnodet,true )); } } return result; }
后序遍历 空指针标记法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 vector<int > pastraversal (TreeNode* root) { vector<int >result; TreeNode* cur= root; stack<TreeNode*>st; if (root != NULL ) st.push (root); while (!st.empty ()) { cur = st.top (); if (cur!=NULL ) { st.pop (); st.push (cur); st.push (NULL ); if (cur->right)st.push (cur->right); if (cur->left)st.push (cur->left); }else { st.pop (); cur = st.top (); result.push_back (cur->val); st.pop (); } } return result; }
boolean标记法
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 vector<int > pastraversal (TreeNode* root) { vector<int >result; stack<pair<TreeNode*,bool >>st; if (root!=nullptr )st.push (make_pair (root,false )); while (!st.empty ()) { auto curnode = st.top ().first; auto visited = st.top ().second; st.pop (); if (visited) { result.push_back (curnode->val); continue ; } st.push (make_pair (curnodet,true )); if (curnode->right)st.push (make_pair (curnode->right,false )); if (curnode->left)st.push (make_pair (curnode->left,false )); } } return result; }
层序遍历 广度优先遍历/层序遍历(迭代法和递归法)(正向) 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 27 28 29 30 31 32 33 34 35 36 37 void order (TreeNode* cur, vector<vector<int >>& result, int depth) { if (cur == nullptr ) return ; if (result.size () == depth) result.push_back (vector <int >()); result[depth].push_back (cur->val); order (cur->left, result, depth + 1 ); order (cur->right, result, depth + 1 ); } vector<vector<int >> levelOrder (TreeNode* root) { vector<vector<int >> result; int depth = 0 ; order (root, result, depth); return result; } vector<vector<int >> levelOrder (TreeNode* root) { queue<TreeNode*> que; if (root != NULL ) que.push (root); vector<vector<int >> result; while (!que.empty ()) { int size = que.size (); vector<int > vec; for (int i = 0 ; i < size; i++) { TreeNode* node = que.front (); que.pop (); vec.push_back (node->val); if (node->left) que.push (node->left); if (node->right) que.push (node->right); } result.push_back (vec); } return result; }
反向层序遍历(迭代法)(正向遍历reverse一下就行) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 vector<vector<int >> levelOrder (TreeNode* root) { queue<TreeNode*> que; if (root != NULL ) que.push (root); vector<vector<int >> result; while (!que.empty ()) { int size = que.size (); vector<int > vec; for (int i = 0 ; i < size; i++) { TreeNode* node = que.front (); que.pop (); vec.push_back (node->val); if (node->left) que.push (node->left); if (node->right) que.push (node->right); } result.push_back (vec); } reverse (result.begin (),result.end ()); return result; }
对称二叉树的判断 递归
层序遍历
队列
栈
二叉树的高度与深度 后续遍历 从下到上求高度
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution {public : int getdepth (TreeNode* node) { if (node == NULL ) return 0 ; int leftdepth = getdepth (node->left); int rightdepth = getdepth (node->right); int depth = 1 + max (leftdepth, rightdepth); return depth; } int maxDepth (TreeNode* root) { return getdepth (root); } };
前序遍历 从上到下求深度
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 27 class Solution {public : int result; void getdepth (TreeNode* node, int depth) { result = depth > result ? depth : result; if (node->left == NULL && node->right == NULL ) return ; if (node->left) { depth++; getdepth (node->left, depth); depth--; } if (node->right) { depth++; getdepth (node->right, depth); depth--; } return ; } int maxDepth (TreeNode* root) { result = 0 ; if (root == NULL ) return result; getdepth (root, 1 ); return result; } };
迭代法 层序遍历
隐藏回溯:if (cur->left) traversal(cur->left, path + “->”, result); // 左 回溯就隐藏在这里
那么在如上代码中,貌似没有看到回溯的逻辑,其实不然,回溯就隐藏在traversal(cur->left, path + "->", result);中的 path + "->"。 每次函数调用完,path依然是没有加上”->” 的,这就是回溯了。
map排序 sort cmp给的是前两个(或者相邻两个(从前往后))应满足的关系 map先转化成数组
1 2 3 4 5 6 bool static cmp (const pair<int , int >& a, const pair<int , int >& b) { return a.second > b.second; } vector<pair<int , int >> vec (map.begin (), map.end ()); sort (vec.begin (), vec.end (), cmp);
二叉搜索树 找众数,即出现最多次,可以用
1 2 3 4 5 6 if (count > maxCount) { maxCount = count; result.clear (); result.push_back (cur->val); }
遍历一条边和搜索整个数的区别?
找到了就一路返回
二叉搜索树是从上到下找公共祖先
二叉搜索树可以尝试用迭代法,因为只有一条路径,不需要回溯
回溯 横纵方向,横向集合大小for循环处理,纵向递归处理树的深度
在递归的过程中增加闸门 backtracking
五大类问题
组合 切割 子集 排列 棋盘
组合问题 回溯三部曲
回溯模板
1 2 3 4 5 6 7 8 9 10 11 12 void backtracking (参数) { if (终止条件) { 存放结果; return ; } for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 处理节点; backtracking (路径,选择列表); 回溯,撤销处理结果 } }
组合问题剪枝
1 n-(k-path.size ())+1 来代替n;可以用n=4 ,k=3 来举例子,当.size ()=0 的时候,只需要遍历1 ,234 都被剪掉了 这里用<=要方便一些
由于无法控制嵌套的for循环层数,所以要用回溯算法。回溯算法抽象成一个n叉树
组合问题(取k个数控制树的深度),for循环的范围是集合宽度
组合剪枝,条件剪枝和组合个数剪枝
输出细节
1 ["" ]不合法,需要转化成[],可以用.clear ()
private中不需要传参也可以用
1 2 3 backtracking (candidates, target, i); backtracking (candidates, target, i + 1 );
1 2 3 4 5 6 7 8 9 10 11 12 13 find (result.begin (), result.end (), path) != result.end ()vector<int > digits = {} set转数组 unordered_set<int > set = {5 , 2 , 8 , 1 } vector<int > vec (set.begin (), set.end ()); set添加元素 unordered_set<int , int > people; people.emplace (1 );
分割问题 可以把判断放在单层搜索逻辑中
字符串操作:’’是char “”是string
在某点插入某个符号 s.insert(s.begin() + i + 1 , ‘.’);
字符串删除:注意
s.erase(s.begin() + i + 1); 这里s.begin()是迭代器,所以删除的是那一位置的元素
s.erase(1); 这里删除的是第一个索引包括之后的所有元素
子集问题 直接加进去就行
排列问题 采用used数组,used数组用来去重或者排列
最主要的是去重
数层去重和树枝去重:组合总和2视频
棋盘问题 N皇后 字符串初始化
1 2 3 int n = 4 ; vector<string> board (n, string(n, '.' )) ;
数独
二维递归
贪心算法 动态规划 图论 默写 二叉树递归遍历:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void pretraversal (TreeNode* cur,vector<int >&vec) { if (cur==NULL )return ; vec.push_back (cur->val); pretraversal (cur->left,vec); pretraversal (cur->right,vec); } void midtraversal (TreeNode* cur,vector<int >&vec) { if (cur==NULL )return ; pretraversal (cur->left,vec); vec.push_back (cur->val); pretraversal (cur->right,vec); } void pastraversal (TreeNode* cur,vector<int >&vec) { if (cur==NULL )return ; pretraversal (cur->left,vec); pretraversal (cur->right,vec); vec.push_back (cur->val); }
二叉树的统一迭代遍历:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 vector<int >itertraversal (TreeNode* root){ vector<int >result; stack<pair<TreeNode*,bool >>st; if (root!=nullptr )st.push (make_pair (root,false )); while (!st.empty ()) { auto curnode = st.top ().first; auto visited = st.top ().second; st.pop (); if (visited){ result.push_back (curnode->val); }else { if (curnode->right)st.push ((make_pair (curnode->right,false )); if (curnode->left)st.push ((make_pair (curnode->left,false )); st.push (make_pair (curnode,true )); } } return result; }
二叉树的迭代层序遍历:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 vector<vector<int >>leveltraversal ((TreeNode* root){ vector<vector<int >>result; queue<int >que; if (root!=nullptr )que.push (root) while (!que.empty ()) { vector<int >vec; int len = que.size (); for (int i = 0 ;i<len;i++) { TreeNode* cur = que.front (); que.pop (); vec.push_back (cur->val); if (cur->left)que.push (cur->left); if (cur->right)que.push (cur->right); } result.push_back (vec); } return result; }