常用代码模版

数据结构

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]);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值