常用代码模版
数据结构
Trie树
const int N = 10010;
int s[N][26],cnt[N],idx;
void insert(string str){
int p=0;
for(int i=0;i<str.size();i++){
int u=str[i]-'a';
if(!s[p][u])s[p][u]=++idx;
p=s[p][u];
}
cnt[p]++;
}
int query(string str){
int p=0;
for(int i=0;i<str.size();i++){
int u=str[i]-'a';
if(!s[p][u])return 0;
p=s[p][u];
}
return cnt[p];
}
算法模版
组合
无重复元素,求组合总和
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> combinationSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
dfs(nums, 0, 0, target);
return res;
}
void dfs(vector<int>& nums, int u, int sum, int target){
if(sum == target) {
res.push_back(path);
return;
}
for(int i = u;i < nums.size();i++){
if(sum > target) continue;
path.push_back(nums[i]);
dfs(nums, i, sum + nums[i], target);
path.pop_back();
}
}
};
有重复元素,求组合总和
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> combinationSum2(vector<int>& cs, int target) {
sort(cs.begin(), cs.end());
dfs(cs, 0, target);
return res;
}
void dfs(vector<int> & cs, int u, int target){
if(target == 0){
res.push_back(path);
return;
}
for(int i = u; i < cs.size(); i ++){
if(target < cs[i]) continue;
if(i > u && cs[i] == cs[i-1]) continue;
path.push_back(cs[i]);
dfs(cs, i + 1, target - cs[i]);
path.pop_back();
}
}
};
全排列
无重复数字
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> st(nums.size(), false);
dfs(nums, 0, st);
return res;
}
void dfs(vector<int>& nums, int u, vector<bool>& st){
if(u == nums.size()) {
res.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i ++ ){
if(st[i]) continue;
st[i] = true;
path.push_back(nums[i]);
dfs(nums, u + 1, st);
path.pop_back();
st[i] = false;
}
}
};
有重复数字,返回所有不重复全排列
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<bool> st(nums.size(), false);
sort(nums.begin(), nums.end());
dfs(nums, 0, st);
return res;
}
void dfs(vector<int>& nums, int u, vector<bool>& st){
if(u == nums.size()) {
res.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i ++ ) {
if(i && nums[i]==nums[i-1]&&!st[i-1]) continue;
if(st[i]) continue;
st[i] = true;
path.push_back(nums[i]);
dfs(nums, u + 1, st);
path.pop_back();
st[i] = false;
}
}
};
二分查找模版
#查找小于等于val的最大的数
int binary_search(int nums[],int val){
int l=0,r=N-1;
while(l<r){
int mid=(l+r+1)>>1;
if(nums[mid]<=val)l=mid;
else r=mid-1;
}
return l;
}
#查找大于等于val的最小的数
int binary_search(int nums[],int val){
int l=0,r=N-1;
while(l<r){
int mid=(l+r)>>1;
if(nums[mid]>=val)r=mid;
else l=mid+1;
}
return l;
}
快速排序模版
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
归并排序模版
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
堆排序
// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1
// ph[k]存储第k个插入的点在堆中的位置
// hp[k]存储堆中下标是k的点是第几个插入的
int h[N], ph[N], hp[N], size;
// 交换两个点,及其映射关系
void heap_swap(int a, int b)
{
swap(ph[hp[a]],ph[hp[b]]);
swap(hp[a], hp[b]);
swap(h[a], h[b]);
}
void down(int u)
{
int t = u;
if (u * 2 <= size && h[u * 2] < h[t]) t = u * 2;
if (u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
if (u != t)
{
heap_swap(u, t);
down(t);
}
}
void up(int u)
{
while (u / 2 && h[u] < h[u / 2])
{
heap_swap(u, u / 2);
u >>= 1;
}
}
// O(n)建堆
for (int i = n / 2; i; i -- ) down(i);
LRU
class LRUCache {
public:
struct Node {
int key, val;
Node *left, *right;
Node(int _key, int _val): key(_key), val(_val), left(NULL), right(NULL) {}
}*L, *R;
unordered_map<int, Node*> hash;
int n;
void remove(Node* p) {
p->right->left = p->left;
p->left->right = p->right;
}
void insert(Node* p) {
p->right = L->right;
p->left = L;
L->right->left = p;
L->right = p;
}
LRUCache(int capacity) {
n = capacity;
L = new Node(-1, -1), R = new Node(-1, -1);
L->right = R, R->left = L;
}
int get(int key) {
if (hash.count(key) == 0) return -1;
auto p = hash[key];
remove(p);
insert(p);
return p->val;
}
void put(int key, int value) {
if (hash.count(key)) {
auto p = hash[key];
p->val = value;
remove(p);
insert(p);
} else {
if (hash.size() == n) {
auto p = R->left;
remove(p);
hash.erase(p->key);
delete p;
}
auto p = new Node(key, value);
hash[key] = p;
insert(p);
}
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
LFU
struct Node{
int key,val,freq;
Node(int _key, int _val, int _freq):key(_key),val(_val),freq(_freq){}
};
class LFUCache {
int minfreq,capacity;
unordered_map<int, list<Node>::iterator> key_table;
unordered_map<int, list<Node>> freq_table;
public:
LFUCache(int _capacity) {
minfreq=0;
capacity=_capacity;
key_table.clear();
freq_table.clear();
}
int get(int key) {
if(capacity==0)return -1;
auto it=key_table.find(key);
if(it==key_table.end())return -1;
list<Node>::iterator node=it->second;
int val=node->val,freq=node->freq;
freq_table[freq].erase(node);
if(freq_table[freq].size()==0){
freq_table.erase(freq);
if(minfreq==freq)minfreq+=1;
}
freq_table[freq+1].push_front(Node(key,val,freq+1));
key_table[key]=freq_table[freq+1].begin();
return val;
}
void put(int key, int value) {
if (capacity == 0) return;
auto it = key_table.find(key);
if (it == key_table.end()) {
// 缓存已满,需要进行删除操作
if (key_table.size() == capacity) {
// 通过 minFreq 拿到 freq_table[minFreq] 链表的末尾节点
auto it2 = freq_table[minfreq].back();
key_table.erase(it2.key);
freq_table[minfreq].pop_back();
if (freq_table[minfreq].size() == 0) {
freq_table.erase(minfreq);
}
}
freq_table[1].push_front(Node(key, value, 1));
key_table[key] = freq_table[1].begin();
minfreq = 1;
} else {
// 与 get 操作基本一致,除了需要更新缓存的值
list<Node>::iterator node = it -> second;
int freq = node -> freq;
freq_table[freq].erase(node);
if (freq_table[freq].size() == 0) {
freq_table.erase(freq);
if (minfreq == freq) minfreq += 1;
}
freq_table[freq + 1].push_front(Node(key, value, freq + 1));
key_table[key] = freq_table[freq + 1].begin();
}
}
};
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache* obj = new LFUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
并查集
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
判断一个数是不是k的倍数
class Solution {
public:
bool isPowerOfFour(int n,int k) {
if (n == 0) return false;
while (n != 1) {
if (n % k != 0) return false;
n = n / k;
}
return true;
}
};
求下一个排列
class Solution {
public:
void next_permutation(vector<int>& nums) {
int i = nums.size() - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
if (i >= 0) {
int j = nums.size() - 1;
while (j >= 0 && nums[i] >= nums[j]) {
j--;
}
swap(nums[i], nums[j]);
}
reverse(nums.begin() + i + 1, nums.end());
}
};
快速幂
int quick_mi(int a, int k, int q)
{
int res = 1;
while(k){
if(k&1) res = (long long) res * a % p;
k >> 1;
a = (long long) a * a;
}
return res;
}
字符串匹配
//朴素匹配
bool match(string s,string p){
for(int i=0;i<=s.size()-p.size();i++){
int j=0;
for(int j=0;j<p.size();j++){
if(s[i+j]!=p[j])break;
}
if(j==p.size())return true;
}
return false
}
//KMP匹配
bool match(string s,string p){
int n=s.size(),m=p.size();
int ne[m];
for(int i = 1, j = 0; i < m; i++)
{
while(j && p[i] != p[j]) j = ne[j];
if(p[i] == p[j]) j++;
ne[i] = j;
}
//匹配操作
for(int i = 0, j = 0; i < n; i++)
{
while(j && s[i] != p[j]) j = ne[j];
if(s[i] == p[j]) j++;
if(j == m)
{
//return true;
printf("%d ", i - m);
//j = ne[j]; //再次继续匹配
}
}
return false;
}
动态规划
01背包问题
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int f[MAXN]; //
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++) {
int v, w;
cin >> v >> w; // 边输入边处理
for(int j = m; j >= v; j--)
f[j] = max(f[j], f[j - v] + w);
}
cout << f[m] << endl;
return 0;
}
完全背包问题
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int f[MAXN];
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
int v,w;
cin>>v>>w;
for(int j=v;j<=m;j++){
f[j]=max(f[j],f[j-v]+w);
}
}
cout<<f[m]<<endl;
return 0;
}
最长上升子序列
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
vector<int> dp(n,0);
for(int i=0;i<n;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
dp[i]=max(dp[i],dp[j]+1);
}
}
}
return *max_element(dp.begin(),dp.end());
}
};
最长公共子序列
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int len1=text1.size(),len2=text2.size();
vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));
for(int i=1;i<len1+1;i++){
for(int j=1;j<len2+1;j++){
if(text1[i-1]==text2[j-1])dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
return dp[len1][len2];
}
};
编辑距离
class Solution {
public:
int minDistance(string word1, string word2) {
int len1=word1.size();
int len2=word2.size();
if(len1*len2==0)return len1+len2;
vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));
for(int i=len1;i>=0;i--)dp[i][0]=i;
for(int j=len2;j>=0;j--)dp[0][j]=j;
for(int i=1;i<len1+1;i++){
for(int j=1;j<len2+1;j++){
if(word1[i-1]==word2[j-1])dp[i][j]=dp[i-1][j-1];
else dp[i][j]=min(min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+1);
}
}
return dp[len1][len2];
}
};
二叉树
前序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
//递归版
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root, res);
return res;
}
void traversal(TreeNode* root, vector<int> &vec){
if(root==nullptr)return;
vec.push_back(root->val);
traversal(root->left,vec);
traversal(root->right,vec);
}
};
//迭代版
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if (root == nullptr) {
return res;
}
stack<TreeNode*> stk;
TreeNode* node = root;
while (!stk.empty() || node != nullptr) {
while (node != nullptr) {
res.emplace_back(node->val);
stk.emplace(node);
node = node->left;
}
node = stk.top();
stk.pop();
node = node->right;
}
return res;
}
};
中序遍历
//递归版
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
vec.push_back(cur->val); // 中
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root, result);
return result;
}
};
//迭代版
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> result;
if (root == NULL) return result;
st.push(root);
while (!st.empty()) {
TreeNode* node = st.top(); // 中
st.pop();
result.push_back(node->val);
if (node->right) st.push(node->right); // 右(空节点不入栈)
if (node->left) st.push(node->left); // 左(空节点不入栈)
}
return result;
}
};
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> stk;
while(root||stk.size()){
while(root){
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
res.push_back(root->val);
root = root->right;
}
return res;
}
后序遍历
//递归版
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root, res);
return res;
}
void traversal(TreeNode* root, vector<int> &vec){
if(root==nullptr)return;
traversal(root->left,vec);
traversal(root->right,vec);
vec.push_back(root->val);
}
};
//迭代版
class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) {
vector<int> res;
if (root == nullptr) {
return res;
}
stack<TreeNode *> stk;
TreeNode *prev = nullptr;
while (root != nullptr || !stk.empty()) {
while (root != nullptr) {
stk.emplace(root);
root = root->left;
}
root = stk.top();
stk.pop();
if (root->right == nullptr || root->right == prev) {
res.emplace_back(root->val);
prev = root;
root = nullptr;
} else {
stk.emplace(root);
root = root->right;
}
}
return res;
}
};
层序遍历
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int n=q.size();
vector<int> a;
while(n--){
TreeNode* p=q.front();
q.pop();
if(p==nullptr)continue;
a.push_back(p->val);
q.push(p->left);
q.push(p->right);
}
if(!a.empty())res.push_back(a);
}
return res;
}
};
位运算
lowbit返回x的最后一位1
//利用性质 x&-x = x&(~x+1)
int lowbit(int x)
{
return x&-x;
}
# 统计一个数内1的个数
while(x) x-=lowbit(x), cnt++;
图论
邻接表和邻接矩阵(数组模拟)
# 邻接矩阵
g[a][b] 存储 a->b
# 邻接表
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
有向无环图的拓扑排序
bool topsort(){
int hh = 0, tt = -1;
for(int i = 1; i <= n ; i ++){
if(d[i] == 0)q[ ++ tt] = i;
}
while(hh <= tt){
auto t = q[hh++];
for(int i = h[t]; i != -1; i = ne[i]){
int j = e[i];
d[j] --;
if(d[j]==0)q[++tt] = j;
}
}
return tt == n - 1;
}
朴素版的dijktra算法—O(n^2)
int dijkstra() // 求1号点到n号点的最短路距离,如果从1号点无法走到n号点则返回-1
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for(int i = 0; i < n; i++ ){
int t = -1;
for(int j = 1; j <= n; j ++){
if(!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
}
st[t] = true;
for(int j = 1; j <= n ; j++){
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
}
if(dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
堆优化版的dijkstra算法—O(mlogn)
int dijkstra() // 求1号点到n号点的最短路距离,如果从1号点无法走到n号点则返回-1
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> heap;
heap.push({0, 1});
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
Bellman-Ford算法—O(nm)
void bellman_ford()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < k; i ++ )
{
memcpy(last, dist, sizeof dist);
for (int j = 0; j < m; j ++ )
{
auto e = edges[j];
dist[e.b] = min(dist[e.b], last[e.a] + e.c);
}
}
}
SPFA算法—O(m)~O(nm)
int spfa() // 求1号点到n号点的最短路距离,如果从1号点无法走到n号点则返回-1
{
int hh = 0, tt = 0;
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
q[tt ++ ] = 1;
st[1] = true;
while (hh != tt)
{
int t = q[hh ++ ];
if (hh == N) hh = 0;
st[t] = false;
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if (!st[j]) // 如果队列中已存在j,则不需要将j重复插入
{
q[tt ++ ] = j;
if (tt == N) tt = 0;
st[j] = true;
}
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
Floyd算法—O(n^3)
void floyd()
{
for (int k = 1; k <= n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}