• 算法-基础知识汇总


    算法

    STL容器(C++)

    顺序容器

    • 静态的连续数组 array
    • 动态的连续数组 vector
    • 双端队列 deque
    • 单链表 forward_list
    • 双链表 list

    关联容器

    • 唯一键的集合,按照键排序 set
    • 键值对的集合,按照键排序,键是唯一的 map
    • 键的集合,按照键排序 multiset
    • 键值对的集合,按照键排序 multimap

    无序关联容器

    • 唯一键的集合,按照键生成散列 unordered_set
    • 键值对的集合,按照键生成散列,键是唯一的 unordered_map
    • 键的集合,按照键生成散列 unordered_multiset
    • 键值对的集合,按照键生成散列 unordered_multimap

    容器适配器

    • 适配一个容器以提供栈(LIFO数据结构) stack
    • 适配一个容器以提供队列(FIFO数据结构) queue
    • 适配一个容器以提供优先级队列 priority_queue

    详细内容

    1. 顺序容器
      array(C++11开始)
    template <class T, std::size_t N> struct array;
    

    vectordequeforward_listlist

    template <class T, class Allocator = std::allocator<T> > class vector;
    template <class T, class Allocator = std::allocator<T> > class deque;
    template <class T, class Allocator = std::allocator<T> > class forward_list;
    template <class T, class Allocator = std::allocator<T> > class list;
    
    1. 关联容器
      setmapmultisetmultimap
    template<
        class Key,
        class Compare = std::less<Key>,
        class Allocator = std::allocator<Key>
    > class set;
    template<
        class Key,
        class T,
        class Compare = std::less<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> >
    > class map;
    template<
        class Key,
        class Compare = std::less<Key>,
        class Allocator = std::allocator<Key>
    > class multiset;
    template<
        class Key,
        class T,
        class Compare = std::less<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> >
    > class multimap;
    
    1. 无序关联容器
      unordered_setunordered_mapunordered_multisetunordered_multimap
    template<
        class Key,
        class Hash = std::hash<Key>,
        class KeyEqual = std::equal_to<Key>,
        class Allocator = std::allocator<Key>
    > class unordered_set;
    template<
        class Key,
        class T,
        class Hash = std::hash<Key>,
        class KeyEqual = std::equal_to<Key>,
        class Allocator = std::allocator< std::pair<const Key, T> >
    > class unordered_map;
    template<
        class Key,
        class Hash = std::hash<Key>,
        class KeyEqual = std::equal_to<Key>,
        class Allocator = std::allocator<Key>
    > class unordered_multiset;
    template<
        class Key,
        class T,
        class Hash = std::hash<Key>,
        class KeyEqual = std::equal_to<Key>,
        class Allocator = std::allocator< std::pair<const Key, T> >
    > class unordered_multimap;
    
    1. 容器适配器
      stackqueuepriority_queue
    template<
        class T,
        class Container = std::deque<T>
    > class stack;
    template<
        class T,
        class Container = std::deque<T>
    > class queue;
    template<
        class T,
        class Container = std::vector<T>,
        class Compare = std::less<typename Container::value_type>
    > class priority_queue;
    

    数据结构

    二叉树

    1. 前序遍历
    class Solution {
    public:
        void traverse(TreeNode * root, vector<int> &res) {
            if(root==nullptr){
                return;
            }
            res.push_back(root->val);
            traverse(root->left, res);
            traverse(root->right, res);
        }
        vector<int> preorderTraversal(TreeNode* root) {
            vector<int> res;
            traverse(root, res);
            return res;
        }
    };
    
    1. 中序遍历
    class Solution {
    public:
        vector<int> result;
        void travers(TreeNode *root) {
            if(!root) {
                return;
            }
            travers(root->left);
            result.push_back(root->val);
            travers(root->right);
        }
        vector<int> inorderTraversal(TreeNode* root) {
            travers(root);
            return result;
        }
    };
    
    1. 后续遍历
    
    class Solution {
    public:
        void traverse(TreeNode *root, vector<int> &res){
            if(root == nullptr){
                return ;
            }
            traverse(root->left, res);
            traverse(root->right, res);
            res.push_back(root->val);
        }
        vector<int> postorderTraversal(TreeNode* root) {
            vector<int> res;
            traverse(root, res);
            return res;
        }
    };
    
    1. 分层遍历
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root) return res;
        deque<TreeNode *> q;
        q.push_back(root);
        int nextLine = 0, printLen = 1;
    
        while(!q.empty()){
            vector<int> p_res;
            while(printLen>0) {
                TreeNode *node = q.front();
                p_res.push_back(node->val);
                printLen--;
                if(node->left) {
                    nextLine++;
                    q.push_back(node->left);
                }
                if(node->right) {
                    nextLine++;
                    q.push_back(node->right);
                }
                q.pop_front();
            }
            swap(printLen, nextLine);
            res.emplace_back(p_res);
        }
        return res;
    }
    
    
    1. 判断对称二叉树
    class Solution {
    public:
        bool isSymmetric(TreeNode *root1, TreeNode *root2) {
            if(root1 == nullptr && root2 == nullptr){
                return true;
            } else if(root1 == nullptr || root2 == nullptr){
                return false;
            }
            if(root1->val == root2->val &&
              isSymmetric(root1->left, root2->right) &&
              isSymmetric(root1->right, root2->left)){
                return true;
            }
            return false;
        }
        bool isSymmetric(TreeNode* root) {
            if(root == nullptr || (root->left == nullptr && root->right == nullptr)){
                return true;
            }
            return isSymmetric(root->left, root->right);
        }
    };
    
    1. 判断平衡树
    class Solution {
    public:
        int depth(TreeNode *root) {
            if(root == 0) {
                return 0;
            }
            return 1 + max(depth(root->right), depth(root->left));
        }
        bool isBalanced(TreeNode* root) {
            if(!root) { return true; }
            return abs(depth(root->left) - depth(root->right)) <= 1 &&
                isBalanced(root->right) && isBalanced(root->left);
        }
    };
    
    1. 分层打印二叉树
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root) return res;
        deque<TreeNode *> q;
        q.push_back(root);
        int nextLine = 0, printLen = 1;
    
        while(!q.empty()){
            vector<int> p_res;
            while(printLen>0) {
                TreeNode *node = q.front();
                p_res.push_back(node->val);
                printLen--;
                if(node->left) {
                    nextLine++;
                    q.push_back(node->left);
                }
                if(node->right) {
                    nextLine++;
                    q.push_back(node->right);
                }
                q.pop_front();
            }
            swap(printLen, nextLine);
            res.emplace_back(p_res);
        }
        return res;
    }
    
    1. 二叉树的最大直径
    class Solution {
    public:
        int ans = 0;
        int depth(TreeNode *root) {
            if(!root) return 0;
            int L = depth(root->left);
            int R = depth(root->right);
            ans = max(L + R, ans);
            return 1 + max(L, R);
        }
        int diameterOfBinaryTree(TreeNode* root) {
            if(!root) return 0;
            depth(root);
            return ans;
        }
    };
    
    1. 验证二叉搜索树
    bool isValidBST(TreeNode* root) {
        if(!root) return true;
        if(!isValidBST(root->left)) {
            return false;
        }
        if(root->val <= pre){
            return false;
        }
        pre = root->val;
        return isValidBST(root->right);
    }
    
    1. 不同的二叉搜索树的组合数
    int numTrees(int n) {
        vector<int> r(n+1);
        r[0] = r[1] = 1;
        for(int i=2;i<n+1;i++) {
            for(int j=1;j<i+1;j++){
                r[i] += r[j-1] * r[i-j];
            }
        }
        return r[n];
    }
    

    双指针法 - 链表

    1. 找到相交链表的重合节点
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(!headA || !headB){
            return nullptr;
        }
        ListNode *pA = headA, *pB = headB;
        while(pA != pB) {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        return pA;
    }
    
    1. K个一组翻转链表
    void reverseRange(ListNode **prev, int k){
        if(!prev || !(*prev)->next || k <= 0) {
            printf("Error cont
    ");
            return;
        }
        ListNode *pPrev = *prev, *pTail = (*prev)->next;
        ListNode *pA = (*prev), *pB = (*prev)->next, *pTmp = nullptr;
        while(k-- > 0 && pB) {
            pTmp = pB->next;
            pB->next = pA;
            pA = pB;
            pB = pTmp;
        }
        pTail->next = pB;
        pPrev->next = pA;
        *prev = pTail;
    }
    ListNode* reverseKGroup(ListNode* head, int k) {
        if(!head || k <= 1 || !head->next){
            return head;
        }
        ListNode pHead(0, head);
        ListNode *pPrev = &pHead, *pNext = pHead.next;
        while(pNext) {
            int i =0 ;
            for(;i<k&&pNext;i++) {
                pNext = pNext->next;
            }
            if(i<k) {break;}
            reverseRange(&pPrev, k);
        }
        return pHead.next;
    }
    
    1. 删除链表的倒数第K个结点
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(!head || n <= 0) return head;
        ListNode pHead(0, head);
        ListNode *p1 = &pHead, *p2 = &pHead;
        int i =0;
        for(;i <n && p1->next; i++){
            p1= p1->next;
        }
        if(i <n ) return head;
        while(p1->next) {
            p1 = p1->next;
            p2 = p2->next;
        }
        p2->next = p2->next->next;
        return pHead.next;
    }
    
    1. 判断链表中是否有环
    bool hasCycle(ListNode *head) {
        if(!head || !head->next) { return false; }
        ListNode *p1 = head, *p2 = head;
        while(p1 && p2 && p2->next) {
            p1 = p1->next;
            p2 = p2->next->next;
            if (p1 == p2) { return true; }
        }
        return false;
    }
    
    1. 链表排序
    ListNode* sortList(ListNode* head) {
        if(!head||!head->next) return head;
        if(!head->next->next) {
            int &a = head->val, &b = head->next->val;
            if(a>b) swap(a, b);
            return head;
        }
        ListNode *p1 = head, *p2 = head;
        while(p2 && p2->next){
            p1 = p1->next;
            p2 = p2->next->next;
        }
        ListNode *head2 = p1->next;
        p1->next = nullptr;
        ListNode pHead;
        ListNode *l1 = sortList(head), *l2 = sortList(head2), *p = &pHead;
        while(l1 && l2) {
            if(l1->val < l2->val) {
                p->next = l1;
                l1 = l1->next;
            } else {
                p->next = l2;
                l2 = l2->next;
            } 
            p = p->next;
        }
        if(l1) p->next = l1;
        if(l2) p->next = l2;
        return pHead.next;
    }
    

    排序变换 - 链表

    1. 合并两个有序链表
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(!l1)return l2;
        if(!l2)return l1;
        ListNode head(0);
        auto p=&head;
        while(l1&&l2){
            if(l1->val>l2->val){
                p->next=l2;
                l2=l2->next;
                p=p->next;
            }else{
                p->next=l1;
                l1=l1->next;
                p=p->next;
            }
        }   
        if(!l1&&l2){p->next=l2;}
        else if(l1&&!l2){p->next=l1;}
        return head.next;
    }
    

    双指针法 - 数组

    1. 将数组中的所有0移动到末尾
    void moveZeroes(vector<int>& nums) {
        if(nums.empty()) {
            return;
        }
        deque<int> q;
        for(int i = 0; i < nums.size(); i++) {
            if(nums[i] == 0){
                q.push_back(i);
            } else {
                if(!q.empty()){
                    swap(nums[i], nums[q.front()]);
                    q.pop_front();
                    q.push_back(i);
                }
            }
        }
    }
    
    void moveZeroes(vector<int>& nums) {
        int n = nums.size(), left = 0, right = 0;
        while (right < n) {
            if (nums[right]) {
                swap(nums[left], nums[right]);
                left++;
            }
            right++;
        }
    }
    
    1. 接雨水
    int trap(vector<int>& height) {
        int n = height.size();
        int Lmax=0, Rmax=0, sum=0;
        vector<int> maxL(n, 0), maxR(n, 0);
        for(int i =0;i <n;i++){
            Lmax=max(Lmax, height[i]);
            maxL[i]=Lmax;
        }
        for(int i=n-1; i>=0;i--){
            Rmax=max(Rmax, height[i]);
            maxR[i]=Rmax;
        }
        for(int i=0;i<n;i++){
            sum+=(max(0,min(maxR[i],maxL[i])-height[i]));
        }
        return sum;
    }
    
    1. 盛水最多的容器
    int maxArea(vector<int>& height) {
        int i = 0, j = height.size() - 1;
        int ans = 0;
        for(;i<=j;) {
            int h1 = height[i], h2 = height[j];
            ans = max(ans, min(h1, h2) * (j-i));
            h1 > h2 ? j-- : i++;
        }
        return ans;
    }
    
    1. 删除排序数组中的重复项
    int removeDuplicates(vector<int>& nums) {
        if(nums.size() <= 1) return nums.size();
        int i = 1, j = 1, last = nums[0];
        for(;j<nums.size();j++) {
            if(nums[j] != last) {
                last=nums[j];
                swap(nums[i], nums[j]);
                i++;
            }
        }
        return i;
    }
    

    计数原理

    1. 出现一半次数以上的元素
    int majorityElement(vector<int>& nums) {
        if (nums.empty()) return 0;
        int times = 1, prev = nums[0];
        for(int i = 1; i< nums.size(); i ++){
            if(prev == nums[i]){
                times++;
            } else {
                times--;
                if(times <= 0){
                    times = 1;
                    prev = nums[i];
                }
            }
        }
        return prev;
    }
    
    1. 跳跃游戏
    bool canJump(vector<int>& nums) {
        int k = 0;
        for(int i = 0; i < nums.size(); i++) {
            if(i > k) return false;
            k = max(k, nums[i] + i);
        }
        return true;
    }
    

    字符串

    1. 最长公共前缀
    string longestCommonPrefix(vector<string>& strs) {
        if(strs.empty()) return "";
        int i = 0, t = 0;
        for(;;i++) {
            if(i>=strs[0].size()) break;
            char c = strs[0][i];
            for(auto &s: strs) {
                if(i>=s.size() || s[i]!=c) {
                    t = 1;
                    break;
                }
            }
            if(t) break;
        }
        return string(strs[0].begin(), strs[0].begin()+i);
    }
    

    区间问题

    1. 区间合并
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> res;
        if(intervals.empty()) return res;
        sort(intervals.begin(), intervals.end(), [](const vector<int> &l1, const vector<int> &l2){
            return l1[0] < l2[0];
        });
        int n = intervals.size();
        for(int i = 0;i < n; i++) {
            int start = intervals[i][0];
            int end = intervals[i][1];
            i++;
            for(;i<n && end >= intervals[i][0];i++){
                end = max(end, intervals[i][1]);
            }
            res.push_back(vector<int>{start,end});
            i--;
        }
        return res;
    }
    

    回溯法

    1. 组合问题 - 子集
    class Solution {
    public:
        vector<int> r;
        vector<vector<int>> res;
        void recall(vector<int> &nums, int start) {
            res.push_back(r);
            for(int i =start; i< nums.size(); i++){
                r.push_back(nums[i]);
                recall(nums, i +1);
                r.pop_back();
            }
        }
        vector<vector<int>> subsets(vector<int>& nums) {
            int n = nums.size();
            recall(nums ,0);
     
            return res;
        }
    };
    
    1. 组合问题 - 全排列
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());
        res.push_back(nums);
        while(next_permutation(nums.begin(), nums.end())){
            res.push_back(nums);
        }
        return res;
    }
    

    数字转换

    1. 罗马数字转整数
    int to_num(char c) {
        switch(c) {
            case 'I': return 1;
            case 'V': return 5;
            case 'X': return 10;
            case 'L': return 50;
            case 'C': return 100;
            case 'D': return 500;
            case 'M': return 1000;
            default : return 0;
        }
        return 0;
    }
    int romanToInt(string s) {
        int sum = 0;
        for(int i =0 ;i < s.size() - 1; i++){
            if(to_num(s[i]) < to_num(s[i+1])){
                sum -= to_num(s[i]);
            } else {
                sum += to_num(s[i]);
            }
        }
        sum+=to_num(s[s.size()-1]);
        return sum;
    }
    

    矩阵问题

    1. 顺时针旋转矩阵
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        for(int i=0;i<n;i++) {
            for(int j=0;j<(n-i);j++){
                // printf("swap [%d,%d]%d, %d
    ",i, j,matrix[i][j], matrix[n-i-1][n-j-1]);
                swap(matrix[j][i], matrix[n-i-1][n-j-1]);
            }
        }
        for(int i=0;i<n/2;i++){
            swap(matrix[i], matrix[n-i-1]);
        }
    }
    
  • 相关阅读:
    BZOJ-1206 虚拟内存 Hash+离散化+Priority_Queue
    BZOJ-2324 营救皮卡丘 最小费用可行流+拆下界+Floyd预处理
    BZOJ-1834 网络扩容 最小费用最大流+最大流+乱搞
    学习笔记 --- 最小费用最大流
    BZOJ-1927 星际竞速 最小费用最大流+拆点+不坑建图
    BZOJ-1070 修车 最小费用最大流+拆点+略坑建图
    BZOJ-1207 打鼹鼠 DP(LIS)
    BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论
    BZOJ-1189 紧急疏散evacuate BFS预处理+最大流+二分判定+神建模!!
    BZOJ-1822 Frozen Nova 冷冻波 计(jie)算(xi)几何+二分+最大流判定+经典建图
  • 原文地址:https://www.cnblogs.com/liutianchen/p/14290879.html
Copyright © 2020-2023  润新知