C++ leetcode刷题代码模板

一、二分查找

1、基础二分查找

int binarySearch(int[] nums, int target) {
     
    int left = 0; 
    int right = nums.length - 1; // 注意

    while(left <= right) {
     
        int mid = left + (right - left) / 2;
        if(nums[mid] == target)
            return mid; 
        else if (nums[mid] < target)
            left = mid + 1; // 注意
        else if (nums[mid] > target)
            right = mid - 1; // 注意
    }
    return -1;
}

2、 寻找左侧边界的二分法

int left_bound(int[] nums, int target) {
     
    int left = 0, right = nums.length - 1;
    // 搜索区间为 [left, right]
    while (left <= right) {
     
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
     
            // 搜索区间变为 [mid+1, right]
            left = mid + 1;
        } else if (nums[mid] > target) {
     
            // 搜索区间变为 [left, mid-1]
            right = mid - 1;
        } else if (nums[mid] == target) {
     
            // 收缩右侧边界
            right = mid - 1;
        }
    }
    // 检查出界情况
    if (left >= nums.length || nums[left] != target)
        return -1;
    return left;
}

3、寻找右侧边界的二分法

int right_bound(int[] nums, int target) {
     
    int left = 0, right = nums.length - 1;
    while (left <= right) {
     
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
     
            left = mid + 1;
        } else if (nums[mid] > target) {
     
            right = mid - 1;
        } else if (nums[mid] == target) {
     
            // 这里改成收缩左侧边界即可
            left = mid + 1;
        }
    }
    // 这里改为检查 right 越界的情况,见下图
    if (right < 0 || nums[right] != target)
        return -1;
    return right;
}

二、排序

1、C++封装好的sort函数+lambada表达式

Lambada使用外部数据要在[]中加入&符号。

class Solution {
     
public:
    string frequencySort(string s) {
     
        unordered_map<char, int> m;
        for (char c : s) ++m[c];
        sort(s.begin(), s.end(), [&](char& a, char& b){
     
            return m[a] > m[b] || (m[a] == m[b] && a < b);
        });
        return s;
    }
};

2、快排模板(左闭右闭二分法)

void quickSort(vector<int>& nums,int left,int right){
     
        if(left + 1 >= right)   return;

        int first = left,last = right - 1,key = nums[first];

        while(first < last){
     
            while(first < last && nums[last] >= key) --last;
            nums[first] = nums[last];
            while(first < last && nums[first] <= key)    ++first;
            nums[last] = nums[first];
        }

        nums[first] = key;
        quickSort(nums,left,first);
        quickSort(nums,first + 1,right);
    }

3、归并排序

void mergeSort(vector<int>& nums,int left,int right){
     
        if(left + 1 >= right)   return;

        int mid = left + (right - left) / 2;
        mergeSort(nums,left,mid);
        mergeSort(nums,mid,right);

        int first(left),second(mid),cur(0);
        vector<int> tmp(right - left,0);
        while(cur < (right - left)){
     
            if(second == right || (first < mid && nums[first] <= nums[second])){
     
                tmp[cur++] = nums[first++];
            }else{
     
                tmp[cur++] = nums[second++];
            }
        }

        for(int i = left;i < right;++i){
     
            nums[i] = tmp[i - left];
        }
    }

4、插入排序

void insertion_sort(vector<int>& nums,int left,int right){
     
        for(int i = 0;i < right;++i){
     
            for(int j = i;j > 0 && nums[j] < nums[j - 1];--j)  swap(nums[j],nums[j - 1]);
        }
    }

三、BFS


四、DFS


五、回溯法


六、树

1、递归


2、迭代


3、前序遍历


4、中序遍历


5、后序遍历

class Solution {
     
public:
    vector<int> postorderTraversal(TreeNode* root) {
     
        vector<int> res;
        if (!root) return res;
        stack<TreeNode*> st;
        st.push(root);
        while (!st.empty()) {
     
            TreeNode* node = st.top(); st.pop();
            if (!node) continue;
            res.push_back(node->val);
            st.push(node->left);
            st.push(node->right);
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

七、构建完全二叉树


八、并查集

// 并查集
class UnionFind {
     
private:
    vector<int> roots;
public:
    UnionFind(int n) {
     
        roots.resize(n);
        for(int i = 0; i < n; i++) {
     
            roots[i] = i;
        }
    }

    int find(int i) {
     
        if (roots[i] == i) {
     
            return i;
        }
        return roots[i] = find(roots[i]);
    }

    // 判断 p 和 q 是否在同一个集合中
    bool isConnected(int p, int q) {
     
        return find(q) == find(p);
    }

    // 合并 p 和 q 到一个集合中
    void merge(int p, int q) {
     
        roots[find(p)] = find(q);
    }
};

class Solution {
     
    bool isBipartite(vector<vector<int>>& graph) {
     
        // 初始化并查集
        UnionFind *uf = new UnionFind(graph.size());
        // 遍历每个顶点,将当前顶点的所有邻接点进行合并
        for (int i = 0; i < graph.size(); i++) {
     
            for (int w: graph[i]) {
     
                // 若某个邻接点与当前顶点已经在一个集合中了,说明不是二分图,返回 false。
                if (uf->isConnected(i, w)) {
     
                    return false;
                }
                uf->merge(graph[i][0], w);
            }
        }
        return true;
    }
};

九、前缀树


十、图遍历

1、Dijkstra 算法(还没来得及封装,先凑活一下)

int cityNum,roateNum;    
vector<vector<int>> map;  // 辅助工具,出发城市,到达城市,距离
vector<bool> mark;  // 标记,这个最短路径有没有走过
vector<int> dis;   // 辅助距离数组

void dijkstra(int start)
{
     
    // 初始化
    mark.resize(cityNum,false);
    dis.resize(cityNum);

    for(int i=0;i<cityNum;i++)
        dis[i]=map[start][i];
    mark[start]=true;
    dis[start]=0;

    // 不断地更新
    int min;    // 当前阶段的最短路径
    int k;  // 当前最短路径的标号
    for(int i=1;i<cityNum;i++)
    {
     
        min=INT_MIN;
        for(int j=0;j<cityNum;j++)
        {
     
            // 没有走过,而且是新的最短路径
            if(!mark[j]&&dis[j]<min)
            {
     
                min=dis[j];
                k=j;
            }
        }

        // 整合新的最短路径
        mark[k]=true;
        for(int j=0;j<cityNum;j++)
            if(!mark[j]&&dis[j]>dis[k]+map[k][j])
                dis[j]=dis[k]+map[k][j];
    }
}

2、Floyd-Warshall 算法

// 我们漂亮的for for for算法,map是读取下来的数据,dis是保存的最短路径
void floyd()
{
     
    for(int i = 1;i <= cityNum;++i){
     
        for(int j = 1;j <= cityNum;++j){
     
            dis[i][j] = map[i][j];
        }
    }
    
    for(int mid = 1;mid <= cityNum;++mid){
     
        for(int from = 1;from <=cityNum;++from){
     
            if(dis[from][mid] == INF)   continue;
            
            for(int to = 1;to <= cityNum;++to){
     
                dis[from][to] = min(dis[from][to],dis[from][mid] + dis[mid][to]);
            }
        }
    }
}

3、Bellman-Ford 算法


十一、最小生成树

1、Kruskal 算法


2、Prim 算法


十二、拓扑排序


十三、双指针


十四、动态规划

1、状态搜索


2、贪心


十五、全排列

1、基础全排列

void backtrack(vector<int>& nums,int pos,vector<vecotr<int>>& res){
     
        if(pos == nums.size() - 1){
     
            res.emplace_back(nums);
            return;
        }

        for(int i = pos;i < nums.size();++i){
     
            if(i > 0 && nums[i] == nums[i - 1])     continue;
            
            swap(nums[pos],nums[i]);
            backtrack(nums,pos + 1);
            swap(nums[pos],nums[i]);
        }
    }

2、基础组合

void backTracking(int n,int k,int pos,vector<int>& helper,vector<vector<int>>& res){
     
        if(helper.size() == k){
     
            res.emplace_back(helper);
            return;
        }

        for(int i = pos + 1;i <= n;++i){
     
            helper.emplace_back(i);
            backTracking(n,k,i,helper,res);
            helper.pop_back();
        }
    }

你可能感兴趣的:(算法练习题,算法)