暑期LeetCode打卡

文章目录

二分

LeetCode 69. Sqrt(x)

class Solution {
public:
    int mySqrt(int x) {
        int l = 0, r = x;
        while(l < r)
        {
            int mid = (long long)l + r + 1 >> 1;
            if(mid <= x/mid)l = mid;
            else r = mid - 1;
        }
        return r;
    }
};
//这里为了防止溢出,加入long long

LeetCode 35. Search Insert Position

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        if(nums.empty() || nums.back() < target)return nums.size();

        int l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] >= target)r = mid;
            else l = mid + 1;
        }
        return r;
    }
};

LeetCode 34. Find First and Last Position of Element in Sorted Array

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.empty())return {-1, -1};

        //找到左边界
        int l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] >= target)r = mid;
            else l = mid + 1;
        }

        if(nums[r] != target)return {-1,-1};
        int start = r;

        //找到右边界
        l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = l + r + 1 >> 1;
            if(nums[mid] <= target)l = mid;
            else r = mid - 1;
        }

        int end = r;
        return {start, end};
    }
};

LeetCode 74. Search a 2D Matrix

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        //判断边界条件
        if(matrix.empty() || matrix[0].empty())return false;

        //用二分去查找,这里有一个换算关系,最后还要判断是不大于
        int n = matrix.size(), m = matrix[0].size();
        int l = 0, r = n * m - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(matrix[mid / m][mid % m] >= target)r = mid;
            else l = mid + 1;
        }

        if(matrix[r / m][r % m] != target)return false;
        return true;
    }
};

LeetCode 153. Find Minimum in Rotated Sorted Array

class Solution {
public:
    int findMin(vector<int>& nums) {
        int l = 0, r = nums.size() - 1;
        //这里是直接二分,找到分界点
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] <= nums.back())r = mid;
            else l = mid + 1;
        }
        return nums[r];
    }
};

LeetCode 33. Search in Rotated Sorted Array

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //首先这里是边界条件
        if(nums.empty())return - 1;

        //通过分段的性质,找到最小的分解线
        int l = 0, r = nums.size() - 1;
        while(l  < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] <= nums.back())r = mid;
            else l = mid + 1;
        }

        //这里判断目标到底是在哪里
        if(target <= nums.back()) r = nums.size() - 1;
        else l = 0, r --;

        //再次进行二分即可找到大于等于target
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] >= target) r = mid;
            else l = mid + 1;
        }

        if(nums[l] == target)return l;
        return -1;
    }
};

LeetCode 278. First Bad Version

// Forward declaration of isBadVersion API.
bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        int l = 1, r = n;
        while(l < r)
        {
            int mid = (long long)l + r >> 1;
            if(isBadVersion(mid)) r = mid;
            else l = mid + 1;
        }
        return r;
    }
};

LeetCode 162. Find Peak Element

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        //这题写法简单,但是思路不明白
        int l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] > nums[mid+1]) r = mid;
            else l = mid + 1;
        }
        return r;
    }
};

LeetCode 287. Find the Duplicate Number

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int l = 1, r = nums.size() - 1;
        //这道题很特殊,利用抽屉,然后可以分成两部分,必然有一部分是多的
        while(l < r)
        {
            int mid = l + r >> 1;

            int cnt = 0;
            for(auto x : nums)
                if(x >= 1 && x <= mid)
                    cnt++;

            if(cnt > mid - 1 + 1)r = mid;
            else l = mid + 1;
        }
        return r;
    }
};

LeetCode 275. H-Index II




class Solution {
public:
    int hIndex(vector<int>& nums) {
        int l = 0, r = nums.size();
        while(l < r)
        {
            int mid = l + r + 1>> 1;
            if(nums[nums.size() - mid] >= mid) l = mid;
            else r = mid - 1;
        }
        return r;
    }
};

链表专题

LeetCode 19. Remove Nth Node From End of List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //因为头结点可能会改变,所有建立了一个虚拟结点,不需要特判
        auto dummy = new ListNode(-1);
        dummy->next = head;

        //建立了一个快慢指针
        auto first = dummy, second = dummy;
        //快指针先走n步
        while(n--) first = first->next;
        //快慢指针一块走,知道快指针走到了空指针了
        while(first->next)
        {
            first = first->next;
            second = second->next;
        }
        //建立连接关系
        second->next = second->next->next;
        return dummy->next;
    }
};

LeetCode 237. Delete Node in a Linked List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        //方法一
        // node->val = node->next->val;
        // node->next = node->next->next;
        //方法二
        *(node) = *(node->next);
    }
};

LeetCode 83. Remove Duplicates from Sorted List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        auto cur = head;
        while(cur)
        {
            //这里有两种情况,一是相同
            if(cur->next && cur->next->val == cur->val)
            {
                cur->next = cur->next->next;
            }
            //第二种情况就是不同拉
            else
            {
                cur = cur->next;
            }
        }
        return head;
    }
};

LeetCode 61. Rotate List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head)return NULL;

        //首先是计算链表的长度是多少呢
        int n = 0;
        for(auto p = head; p; p = p->next)n++;

        //这里旋转n次是不变的,所以是个坑,需要求余
        k %= n;
        //这里的快慢指针也是和之前的题目是一样的
        auto first = head, second = head;
        while(k--) first = first->next;
        while(first->next)
        {
            first = first->next;
            second = second->next;
        }

        //这里再画个图,然后连连线
        first->next = head;
        head = second->next;
        second->next = NULL;

        return head;
    }
};

LeetCode 24. Swap Nodes in Pairs

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //这里因为头结点会变化,所以使用虚拟头结点
        auto dummy = new ListNode(-1);
        dummy->next = head;

        //这里的话,就是两个一组进行处理,然后移动
        for(auto p = dummy; p->next && p->next->next;)
        {
            //画图分析
            auto a = p->next, b = a->next;
            p->next = b;
            a->next = b->next;
            b->next = a;
            //移动
            p = a;
        }
        return dummy->next;
    }
};

LeetCode 206. Reverse Linked List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head) return NULL;

        auto a = head, b = head->next;
        while(b)
        {
            auto c = b->next;
            b->next = a;
            a = b, b = c;
        }
        head->next = NULL;
        return a;
    }
};

LeetCode 92. Reverse Linked List II

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
//不明觉厉
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(m == n) return head;

        auto dummy = new ListNode(-1);
        dummy->next = head;

        auto a = dummy, d = dummy;

        for(int i = 0; i < m - 1; i++) a = a->next;
        for(int i = 0; i < n; i++) d = d->next;

        auto b = a->next, c = d->next;

        for(auto p = b, q = b->next; q != c;)
        {
            auto o = q->next;
            q->next = p;
            p = q, q = o;
        }

        b->next = c;
        a->next = d;

        return dummy->next;      
    }
};

LeetCode 160. Intersection of Two Linked Lists

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //这题的思路非常巧妙,a+b+c
        auto p = headA, q = headB;
        while(p != q)
        {
            if(p) p = p->next;
            else p = headB;
            if(q) q = q->next;
            else q = headA;
        }
        return p;
    }
};

LeetCode 142. Linked List Cycle II

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    //这题的思路也很巧妙
    ListNode *detectCycle(ListNode *head) {
        auto fast = head, slow = head;
        while(slow)
        {
            fast = fast->next;
            slow = slow->next;
            if(slow) slow = slow->next;
            else break;

            if(fast == slow)
            {
                slow = head;
                while(slow != fast)
                {
                    fast = fast->next;
                    slow = slow->next;
                }
                return slow;
            }
        }
        return NULL;
    }
};

LeetCode 148. Sort List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        int n = 0;
        for (ListNode *p = head; p; p = p->next) n ++ ;

        ListNode *dummy = new ListNode(-1);
        dummy->next = head;
        for (int i = 1; i < n; i *= 2)
        {
            ListNode *begin = dummy;
            for (int j = 0; j + i < n; j += i * 2)
            {
                ListNode *first = begin->next, *second = first;
                for (int k = 0; k < i; k ++ )
                    second = second->next;
                int f = 0, s = 0;
                while (f < i && s < i && second)
                    if (first->val < second->val)
                    {
                        begin = begin->next = first;
                        first = first->next;
                        f ++ ;
                    }
                    else
                    {
                        begin = begin->next = second;
                        second = second->next;
                        s ++ ;
                    }

                while (f < i)
                {
                    begin = begin->next = first;
                    first = first->next;
                    f ++ ;
                }
                while (s < i && second)
                {
                    begin = begin->next = second;
                    second = second->next;
                    s ++ ;
                }

                begin->next = second;
            }
        }

        return dummy->next;
    }
};

树专题

LeetCode 98. Validate Binary Search Tree

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    //这种方式和之前的是有区别的,是一种自上而下的方式,根为中间,剩下的必然是在区间内
    bool isValidBST(TreeNode* root) {
        return dfs(root, INT_MIN, INT_MAX);
    }

    bool dfs(TreeNode *root, long long minv, long long maxv)
    {
        if(!root) return true;
        if(root->val < minv || root->val > maxv) return false;
        return dfs(root->left, minv, root->val - 1ll) && dfs(root->right, root->val + 1ll, maxv);
    }
};

LeetCode 101. Symmetric Tree

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//方法一
// 1.两个根节点的值要想相等
// 2.左边的左子树和右边的右子树对称
// 3.左边的右子树和右边的左子树对称
// class Solution {
// public:
//     bool isSymmetric(TreeNode* root) {
//         if(!root) return true;
//         return dfs(root->left, root->right);
//     }

//     bool dfs(TreeNode* p, TreeNode* q)
//     {
//         if(!p || !q) return !p && !q;

//         return p->val == q->val && dfs(p->left, q->right) && dfs(p->right, q->left);
//     }
// };
//方法二
//左边:左中右遍历,右边:右中左进行遍历
//这种方法就是用迭代的方式进行的
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        stack<TreeNode*>left, right;
        auto l = root->left, r = root->right;
        while(l || r || left.size() || right.size())
        {
            while(l && r)
            {
                left.push(l), l = l->left;
                right.push(r), r = r->right;
            }

            if(l || r) return false;

            l = left.top(), left.pop();
            r = right.top(), right.pop();

            if(l->val != r->val) return false;

            l = l->right, r = r->left;

        }      
        return true;
    }
};

LeetCode 94. Binary Tree Inorder Traversal

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
// 1.将整棵树的最左边一条链压入栈中
// 2.每次取出栈顶元素,如果它有右子树,则将右子树压入栈中
//这种是一种迭代的方式,后面很多题都会用到
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> stk;

        auto p = root;
        while(p || stk.size())
        {
            while(p)
            {
                stk.push(p);
                p = p->left;
            }

            p = stk.top();
            stk.pop();
            res.push_back(p->val);
            p = p->right;
        }
        return res;
    }
};

LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    unordered_map<int, int> pos;

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        for(int i = 0; i < n; i++)pos[inorder[i]] = i;

        return dfs(preorder, inorder, 0, n-1, 0, n-1);
    }

    TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir)
    {
        if(pl > pr) return NULL;
        int val = preorder[pl];
        int k = pos[val];
        int len = k - il;
        auto root = new TreeNode(val);
        root->left = dfs(preorder, inorder, pl + 1, pl + len, il, k-1);
        root->right = dfs(preorder, inorder, pl + len + 1, pr, k+1, il);
        return root;
    }
};

LeetCode 102. Binary Tree Level Order Traversal

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//因为是层序遍历,这里直接用BFS
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;

        if(!root) return res;

        //使用队列进行bfs,也可以用数组去实现
        queue<TreeNode*> q;
        q.push(root);
        while(q.size())
        {
            //队列的长度就是需要输出的长度
            int len = q.size();
            vector<int> level;

            //一方面需要把数值加到队列中,一方面不要忘记了扩展队列
            for(int i = 0; i < len; i++)
            {
                auto t = q.front();
                q.pop();
                level.push_back(t->val);
                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }

            res.push_back(level);
        }
        return res;
    }
};

LeetCode 236. Lowest Common Ancestor of a Binary Tree

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//这题不是很明白
//如果以root为根的子树中包含p和q,则返回他们最近的公共祖先
//如果只包含p,则返回p
//如果只包含q,则返回q
//如果都不包含,则返回NULL
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || root == p || root == q) return root;

        auto left = lowestCommonAncestor(root->left, p, q);
        auto right = lowestCommonAncestor(root->right, p, q);

        if(!left)return right;
        if(!right)return left;
        return root;
    }
};

LeetCode 297. Serialize and Deserialize Binary Tree

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string res;
        dfs1(root, res);
        return res;
    }

    void dfs1(TreeNode* root, string& res)
    {
        if (!root)
        {
            res += "#,";
            return;
        }
        res += to_string(root->val) + ',';
        dfs1(root->left, res);
        dfs1(root->right, res);
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int u = 0;
        return dfs2(data, u);
    }

    TreeNode* dfs2(string &data, int &u)
    {
        if (data[u] == '#')
        {
            u += 2;
            return NULL;
        }

        int t = 0;
        bool is_minus = false;
        while (data[u] != ',')
        {
            if (data[u] == '-') is_minus = true;
            else t = t * 10 + data[u] - '0';
            u ++ ;
        }
        u ++ ;
        if (is_minus) t = -t;

        auto root = new TreeNode(t);
        root->left = dfs2(data, u);
        root->right = dfs2(data, u);

        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));

LeetCode 543. Diameter of Binary Tree

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//枚举所有的最高点
//递归时需要计算,从当前结点往下走,深层的最大值

class Solution {
public:
    int ans = 0;
    int diameterOfBinaryTree(TreeNode* root) {
        dfs(root);
        return ans;
    }

    int dfs(TreeNode *root)
    {
        if(!root) return 0;
        auto left = dfs(root->left);
        auto right = dfs(root->right);

        ans = max(ans, left + right);
        return max(left+1, right+1);
    }
};

LeetCode 124. Binary Tree Maximum Path Sum

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//这题和求树的最大直径是很相似的,dfs返回的不是答案,而是深度
class Solution {
public:
    int ans = INT_MIN;
    int maxPathSum(TreeNode* root) {
        dfs(root);
        return ans;
    }

    int dfs(TreeNode *root)
    {
        if(!root) return 0;

        auto left = dfs(root->left);
        auto right = dfs(root->right);

        ans = max(ans, left + root->val + right);
        return max(0, root->val + max(left, right));
    }
};

LeetCode 173. Binary Search Tree Iterator

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//迭代的方式
class BSTIterator {
public:
    stack<TreeNode*> stk;

    BSTIterator(TreeNode* root) {
        while(root)
        {
            stk.push(root);
            root = root->left;
        }
    }

    /** @return the next smallest number */
    int next() {
        auto p = stk.top();
        stk.pop();
        int res = p->val;
        p = p->right;
        while(p)
        {
            stk.push(p);
            p = p->left;
        }
        return res;
    }

    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !stk.empty();
    }
};

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator* obj = new BSTIterator(root);
 * int param_1 = obj->next();
 * bool param_2 = obj->hasNext();
 */

字符串处理

LeetCode 38. Count and Say

class Solution {
public:
    //模拟题
    string countAndSay(int n) {
        string s = "1";
        for(int i = 0; i < n-1; i++)
        {
            string ns;
            for(int j = 0; j < s.size(); j++)
            {
                //常用技巧
                int k = j;
                while(k < s.size() && s[k] == s[j])k++;
                ns += to_string(k - j) + s[j];
                j = k - 1;
            }
            s = ns;
        }
        return s;
    }
};

LeetCode 49. Group Anagrams

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        //每一组的特征在于,排序后一样
        unordered_map<string, vector<string> > hash;
        for(auto str : strs)
        {
            string key = str;
            sort(key.begin(), key.end());
            hash[key].push_back(str);
        }

        vector<vector<string> > res;
        for(auto item : hash) res.push_back(item.second);
        return res;
    }
};

LeetCode 151. Reverse Words in a String

class Solution {
public:
    string reverseWords(string s) {
        //首先翻转每一个单词,然后翻转整个句子就能达到这样的效果
        int k = 0;
        for(int i = 0; i < s.size(); i++)
        {
            while(i < s.size() && s[i] == ' ')i++;
            if(i == s.size())break;
            int j = i;
            while(j < s.size() && s[j] != ' ')j++;
            reverse(s.begin() + i, s.begin() + j);
            if(k) s[k++] = ' ';
            while(i < j)s[k++] = s[i++];
        }
        s.erase(s.begin() + k, s.end());
        reverse(s.begin(), s.end());
        return s;
    }
};

LeetCode 165. Compare Version Numbers

class Solution {
public:
    int compareVersion(string s1, string s2) {
        //这里使用双指针进行比较
        int i = 0, j = 0;
        while(i < s1.size() || j < s2.size())
        {
            int x = i, y = j;
            //x, y分别代表每一段的值,这里用到了常用的编码方式,移动指针
            while(x < s1.size() && s1[x] != '.') x++;
            while(y < s2.size() && s2[y] != '.') y++;
            //将字符转化为数字
            int a = i == x ? 0 : atoi(s1.substr(i, x - i).c_str());
            int b = j == y ? 0 : atoi(s2.substr(j, y - j).c_str());
            if(a > b) return 1;
            if(a < b) return -1;
            //移动到下一段
            i = x + 1, j = y + 1;
        }
        return 0;
    }
};

LeetCode 929. Unique Email Addresses

class Solution {
public:
    int numUniqueEmails(vector<string>& emails) {
        //建立一个hash表,存储不一样的email
        unordered_set<string> hash;
        //遍历所有的email,去伪存真
        for(auto email : emails)
        {
            //找到@的位置,这里用find函数
            int at = email.find("@");
            string name;
            //遍历每一个字母
            for(auto c : email.substr(0, at))
            {
                //+截断
                if(c == '+')
                {
                    break;
                }
                else if(c != '.')
                {
                    name += c;
                }
            }
            //后面一段
            string domain = email.substr(at+1);
            //把处理好的email,存入hash,读取hash大小即可
            hash.insert(name + '@' + domain);
        }
        return hash.size();
    }
};

LeetCode 5. Longest Palindromic Substring

class Solution {
public:
    string longestPalindrome(string s) {
        string res;
        //枚举每一个起点,然后向两边扩展
        for(int i = 0; i < s.size(); i++)
        {
            //奇数的情况
            for(int j = i, k = i; j >= 0 && k < s.size() && s[j] == s[k]; j--, k++)
                if(res.size() < k - j + 1)
                    res = s.substr(j, k - j + 1);
            //偶数的情况
            for(int j = i, k = i + 1; j >= 0 && k < s.size() && s[j] == s[k]; j--, k++)
                if(res.size() < k - j + 1)
                    res = s.substr(j, k - j + 1);
        }
        return res;
    }
};

LeetCode 6. ZigZag Conversion

class Solution {
public:
    string convert(string s, int n) {
        //模拟题
        if(n == 1)return s;
        string res;
        for(int i = 0; i < n; i++)
        {
            if(!i || i == n -1)
            {
                for(int j = i; j < s.size(); j += 2 * (n - 1)) res += s[j];
            }
            else
            {
                for(int j = i, k = 2 * (n - 1) - i; j < s.size() || k < s.size(); j += 2 * (n - 1), k += 2 * (n - 1))
                {
                    if(j < s.size()) res += s[j];
                    if(k < s.size()) res += s[k];
                }
            }
        }
        return res;
    }
};

LeetCode 3. Longest Substring Without Repeating Characters

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //首先可以想到用hash来判断是不是重复数字
        //之后先暴力枚举,发现双指针能优化
        unordered_map<char, int> hash;
        int res = 0;
        for(int i = 0, j = 0; i < s.size(); i++)
        {
            hash[s[i]]++;
            while(hash[s[i]] > 1)hash[s[j++]]--;
            res = max(res, i - j + 1);
        }
        return res;
    }
};

LeetCode 208. Implement Trie (Prefix Tree)

class Trie {
public:

    //Trie对应每一个节点的结构体
    struct Node
    {
        bool is_end;
        Node *son[26];
        Node()
        {
            is_end = false;
            for(int i = 0; i < 26; i++) son[i] = NULL;
        }
    }*root;

    /** Initialize your data structure here. */
    Trie() {
        root = new Node();
    }

    //如果为空,则插入,到了结尾处则标记为true
    /** Inserts a word into the trie. */
    void insert(string word) {
        auto p = root;
        for(auto c : word)
        {
            int u = c - 'a';
            if(p->son[u] == NULL)p->son[u] = new Node();
            p = p->son[u];
        }
        p->is_end = true;
    }

    //查找有没有,中间没有直接return,之后看看结尾标记了
    /** Returns if the word is in the trie. */
    bool search(string word) {
        auto p = root;
        for(auto c : word)
        {
            int u = c - 'a';
            if(p->son[u] == NULL)return false;
            p = p->son[u];
        }
        return p->is_end;
    }

    //这个是只要存在就好,不是结尾也是ok的
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        auto p = root;
        for(auto c : prefix)
        {
            int u = c - 'a';
            if(p->son[u] == NULL)return false;
            p = p->son[u];
        }
        return true;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie* obj = new Trie();
 * obj->insert(word);
 * bool param_2 = obj->search(word);
 * bool param_3 = obj->startsWith(prefix);
 */

LeetCode 273. Integer to English Words

class Solution {
public:
    string small[20] = {"Zero", "One","Two","Three", "Four","Five","Six","Seven","Eight","Nine","Ten", "Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"};
    string decade[10] = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    string big[4] = {"Billion", "Million", "Thousand", ""};

    //这里把每一个分成一段一段的,3个一组
    string numberToWords(int num) {
        //特判为0
        if(!num) return small[0];

        string res;
        for(int i = 1000000000, j = 0; i > 0; i /= 1000, j++)
        {
            if(num >= i)
            {
                res += get_part(num / i) + big[j] + ' ';
                num %= i;
            }
        }    
        while(res.back() == ' ') res.pop_back();
        return res;
    }

    string get_part(int num)
    {
        string res;
        if(num >= 100)
        {
            res += small[num / 100] + " Hundred ";
            num %= 100;
        }
        if(!num) return res;
        if(num >= 20)
        {
            res += decade[num / 10] + ' ';
            num %= 10;
        }
        if(!num) return res;
        res += small[num] + ' ';
        return res;
    }
};

DFS+回溯

LeetCode 17. Letter Combinations of a Phone Number

class Solution {
public:

// state = {""}
// for 每个数字
//     for c = 当前数字的所有备选字母
//         for s = state中的所有字符串
//             s += c

    string chars[8] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    vector<string> letterCombinations(string digits) {
        if(digits.empty()) return vector<string>();

        vector<string> state(1, "");
        for(auto u : digits)
        {
            vector<string> now;
            for(auto c : chars[u - '2'])
                for(auto s : state)
                    now.push_back(s + c);
            state = now;
        }
        return state;
    }
};

LeetCode 79. Word Search

class Solution {
public:
    int n, m;
    //这是四个方向
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = { 0, 1, 0, -1};

    bool exist(vector<vector<char>>& board, string word) {
        if(board.empty() || board[0].empty()) return false;
        n = board.size(), m = board[0].size();

        //对面板上的每一个点都枚举
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                if(dfs(board, i, j, word, 0))
                    return true;
        return false;
    }

    bool dfs(vector<vector<char> >& board, int x, int y, string& word, int u)
    {
        if(board[x][y] != word[u]) return false;
        if(u == word.size() - 1) return true;

        //这里有回溯,要恢复现场
        board[x][y] = '.';
        for(int i = 0; i < 4; i++)
        {
            int a = x + dx[i];
            int b = y + dy[i];
            if(a >= 0 && a < n && b >= 0 && b < m)
                if(dfs(board, a, b, word, u+1))
                    return true;
        }
        board[x][y] = word[u];
        return false;
    }
};

LeetCode 46. Permutations

class Solution {
public:
    int n;
    //用来标记某个数字是否用了
    vector<bool> st;
    //存储最终的答案
    vector<vector<int> > ans;
    //存储当前的答案
    vector<int> path;

    vector<vector<int>> permute(vector<int>& nums) {
        //初始化
        n = nums.size();
        st = vector<bool>(n);

        //深搜+回溯
        dfs(nums, 0);
        return ans;
    }

    void dfs(vector<int>& nums, int u)
    {
        //达到了终止条件
        if(u == n)
        {
            ans.push_back(path);
            return;
        }


        for(int i = 0; i < n; i++)
        {
            if(!st[i])
            {
                //标记现场
                st[i] = true;
                path.push_back(nums[i]);
                dfs(nums, u + 1);
                //恢复现场
                path.pop_back();
                st[i] = false;
            }
        }
    }
};

LeetCode 47. Permutations II

class Solution {
public:
    //这里用全局,值引用,这样就不用重复赋值
    int n;
    //答案
    vector<vector<int> > ans;
    //当前枚举的路径
    vector<int> path;
    //标记数组
    vector<bool> st;

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        //初始化
        n = nums.size();
        st = vector<bool>(n);
        path = vector<int>(n);

        //这里通过排序,使得相同的数字排在一块了,对于相同的数字人为规定一个顺序
        sort(nums.begin(), nums.end());

        dfs(nums, 0, 0);

        return ans;
    }

    void dfs(vector<int>& nums, int u, int start)
    {
        //终止条件
        if(u == n)
        {
            ans.push_back(path);
            return;
        }

        //是否是相同的数字,如果是则接着找
        for(int i = start; i < n; i++)
        {
            if(!st[i])
            {
                st[i] = true;
                path[i] = nums[u];
                dfs(nums, u + 1, u + 1 < n && nums[u+1] == nums[u] ? i : 0);
                st[i] = false;
            }
        }
    }
};

LeetCode 78. Subsets

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        //这里存答案
        vector<vector<int> > res;
        //每个数字有两种状态,所以一共有1 << nums.size()中状态,然后填充答案即可
        for(int i = 0; i < 1 << nums.size(); i++)
        {
            vector<int> now;
            for(int j = 0; j < nums.size(); j++)
            {
                if(i >> j & 1)
                    now.push_back(nums[j]);
            }
            res.push_back(now);
        }
        return res;
    }
};

LeetCode 90. Subsets II

class Solution {
public:
    //常规操作,变量
    vector<vector<int> > ans;
    vector<int> path;

    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        //排个序,这样相同的数字会排在一块
        sort(nums.begin(), nums.end());
        dfs(nums, 0);
        return ans;
    }

    void dfs(vector<int>& nums, int u)
    {
        //终止条件
        if(u == nums.size())
        {
            ans.push_back(path);
            return;
        }

        //这里不一样了,有多少个重复的数字
        int k = 0;
        while(u + k < nums.size() && nums[u + k] == nums[u])k++;
        for(int i = 0; i <= k; i ++)
        {
            dfs(nums, u + k);
            path.push_back(nums[u]);
        }
        for(int i = 0; i <= k; i++)path.pop_back();
    }
};

LeetCode 216. Combination Sum III

class Solution {
public:
    vector<vector<int> > ans;
    vector<int> path;

    vector<vector<int>> combinationSum3(int k, int n) {
        dfs(k, 1, n);
        return ans;
    }

    void dfs(int k, int start, int n)
    {
        if(!k)
        {
            if(!n) ans.push_back(path);
            return;
        }

        for(int i = start; i <= 10 - k; i++)
        {
            path.push_back(i);
            dfs(k - 1, i + 1, n - i);
            path.pop_back();
        }
    }
};

LeetCode 52. N-Queens II

class Solution {
public:
    int ans;
    vector<bool> row, col, diag, anti_diag;

    int totalNQueens(int n) {
        row = col = vector<bool>(n, false);
        diag = anti_diag = vector<bool>(2 * n, false);
        ans = 0;
        dfs(0, 0, 0, n);
        return ans;
    }

    void dfs(int x, int y, int s, int n)
    {
        if (y == n) x ++ , y = 0;
        if (x == n)
        {
            if (s == n) ++ ans;
            return ;
        }

        dfs(x, y + 1, s, n);
        if (!row[x] && !col[y] && !diag[x + y] && !anti_diag[n - 1 - x + y])
        {
            row[x] = col[y] = diag[x + y] = anti_diag[n - 1 - x + y] = true;
            dfs(x, y + 1, s + 1, n);
            row[x] = col[y] = diag[x + y] = anti_diag[n - 1 - x + y] = false;
        }
    }
};

LeetCode 37. Sudoku Solver

class Solution {
public:
    //不明觉厉
    bool row[9][9] = {0}, col[9][9] = {0}, cell[3][3][9] = {0};

    void solveSudoku(vector<vector<char>>& board) {
        for(int i =0 ; i < 9; i++)
        {
            for(int j = 0; j < 9; j++)
            {
                char c = board[i][j];
                if(c != '.')
                {
                    int t = c - '1';
                    row[i][t] = col[j][t] = cell[i / 3][j / 3][t] = true;
                }
            }
        }
        dfs(board, 0, 0);
    }

    bool dfs(vector<vector<char> >& board, int x, int y)
    {
        if(y == 9) x++, y = 0;
        if(x == 9) return true;
        if(board[x][y] != '.') return dfs(board, x, y+1);

        for(int i = 0; i < 9; i++)
        {
            if(!row[x][i] && !col[y][i] && !cell[x / 3][y / 3][i])
            {
                board[x][y] = '1' + i;
                row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = true;
                if(dfs(board, x, y + 1)) return true;
                row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = false;
                board[x][y] = '.';
            }
        }
        return false;
    }
};

LeetCode 473. Matchsticks to Square

class Solution {
public:
// 这题是裁剪的经典题目:
// 首先是依次构造正方的每条边
// 剪枝:
// 1.从大到小枚举所有边
// 2.每条边内部的木棒长度规定成从大到小
// 3.如果当前木棒拼接失败,则跳过接下来所有长度相同的木棒
// 4.如果当前木棒拼接失败,且是当前边的第一个,则直接剪掉当前分支
// 5.如果当前木棒拼接失败,且是当前边的最后一个,则直接剪掉当前分支

    vector<bool> st;

    bool makesquare(vector<int>& nums) {
        int sum = 0;
        for(auto u : nums) sum += u;

        if(!sum || sum % 4) return false;

        sort(nums.begin(), nums.end());

        reverse(nums.begin(), nums.end());

        st = vector<bool>(nums.size());

        return dfs(nums, 0, 0, sum / 4);
    }

    bool dfs(vector<int>& nums, int u, int cur, int length)
    {
        if(cur == length)u++, cur = 0;
        if(u == 4) return true;

        for(int i = 0; i < nums.size(); i++)
        {
            if(!st[i] && cur + nums[i] <= length)
            {
                st[i] = true;
                if(dfs(nums, u, cur + nums[i], length)) return true;
                st[i] = false;
                if(!cur) return false;
                if(cur + nums[i] == length) return false;
                while(i + 1 < nums.size() && nums[i] == nums[i+1]) i++;
            }
        }
        return false;
    }
};

滑动窗口、双指针与单调队列/栈

LeetCode 167. Two Sum II - Input array is sorted

class Solution {
public:
    //首先是暴力枚举->然后观察有无单调性->进行枚举
    vector<int> twoSum(vector<int>& numbers, int target) {
        for(int j = 0, i = numbers.size() - 1; j < numbers.size(); j++)
        {
            while(i-1 > j && numbers[i - 1] + numbers[j] >= target)i--;
            if(numbers[i]+numbers[j] == target) return {j + 1, i + 1};
        }
        return {-1, -1};
    }
};

LeetCode 88. Merge Sorted Array

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int i = m - 1, j = n- 1, k = m + n - 1;
        while(i >= 0 && j >= 0)
        {
            if(nums1[i] > nums2[j]) nums1[k--] = nums1[i--];
            else nums1[k--] = nums2[j--];
        }
        while(j >= 0)nums1[k--] = nums2[j--];
    }
};

LeetCode 26. Remove Duplicates from Sorted Array

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.empty()) return 0;
        //使用双指针
        int k = 1;
        for(int j = 1; j < nums.size(); j++)
            if(nums[j] != nums[j-1])
                nums[k++] = nums[j];
        return k;
    }
};

LeetCode 76. Minimum Window Substring

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> hash;
        int cnt = 0;
        for (auto c : t)
        {
            if (!hash[c]) cnt ++ ;
            hash[c] ++ ;
        }

        string res = "";
        for (int i = 0, j = 0, c = 0; i < s.size(); i ++ )
        {
            if (hash[s[i]] == 1) c ++ ;
            hash[s[i]] -- ;
            while (c == cnt && hash[s[j]] < 0) hash[s[j ++ ]] ++ ;
            if (c == cnt)
            {
                if (res.empty() || res.size() > i - j + 1) res = s.substr(j, i - j + 1);
            }
        }

        return res;
    }
};

LeetCode 32. Longest Valid Parentheses

class Solution {
public:

// 括号序列合法 <=> 所有前缀和 >= 0, 且总和等于0
// )()())
// start 当前枚举的这一段开头
// cnt 前缀和
// ( = 1, ) = -1
// 1.cnt <= 0, start = i + 1, cnt = 0;
// 2.cnt > 0, 继续做
// 3.cnt == 0, [start, i]是一段合法的序列

    int work(string s)
    {
        int res = 0;
        for(int i = 0, start = 0, cnt = 0; i < s.size(); i++)
        {
            if(s[i] == '(') cnt++;
            else
            {
                cnt--;
                if(cnt < 0) start = i + 1, cnt = 0;
                else if(!cnt) res = max(res, i - start+1);
            }
        }
        return res;
    }


    int longestValidParentheses(string s) {
        int res = work(s);
        reverse(s.begin(), s.end());
        for(auto &c : s) c ^= 1;
        return max(res, work(s));
    }
};

LeetCode 155. Min Stack

// MinStack minStack = new MinStack();
// minStack.push(-2);
// minStack.push(0);
// minStack.push(-3);
// minStack.getMin();   --> Returns -3.
// minStack.pop();
// minStack.top();      --> Returns 0.
// minStack.getMin();   --> Returns -2.

class MinStack {
public:
    //首先是定义一个栈和一个最小栈
    stack<int> stk, stk_min;

    /** initialize your data structure here. */
    MinStack() {

    }

    //栈里面就随便加,最小栈要比较下,最小栈存的是当前栈中最小的数值
    //如果比较小,则放入栈中,否则则不放入
    void push(int x) {
        stk.push(x);
        if(stk_min.empty()) stk_min.push(x);
        else stk_min.push(min(x, stk_min.top()));
    }

    //弹出的话,就是一起弹处来就可以了
    void pop() {
        stk.pop();
        stk_min.pop();
    }

    //栈顶元素
    int top() {
        return stk.top();
    }

    //栈顶元素,这里要注意,stack和vector函数有点像,但是不一样呢
    int getMin() {
        return stk_min.top();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

LeetCode 42. Trapping Rain Water

class Solution {
public:
    int trap(vector<int>& height) {
        int res = 0;
        stack<int> stk;
        for (int i = 0; i < height.size(); i ++ )
        {
            int last = 0;
            while (stk.size() && height[stk.top()] <= height[i])
            {
                int t = stk.top(); stk.pop();
                res += (i - t - 1) * (height[t] - last);
                last = height[t];
            }
            if (stk.size()) res += (i - stk.top() - 1) * (height[i] - last);
            stk.push(i);
        }
        return res;
    }
};

LeetCode 84. Largest Rectangle in Histogram

class Solution {
public:
/*

单调栈:查找每个数左侧第一个比它小的数

单调队列:滑动窗口中的最值

如何枚举处所有的情况呢?
枚举所有柱形的上边界,作为整个矩形的上边界
然后求出左右边界:
1.找出左边离它最近的,比它小的柱形
1.找出右边离它最近的,比它小的柱形
*/
//首先来说是确认上边界,然后找到左右的边界
    int largestRectangleArea(vector<int>& heights) {
        //高度
        int n = heights.size();
        //定义两个左右的边界
        vector<int> left(n), right(n);

        //这里是利用单调栈的性质,是一个升序
        stack<int> stk;
        for(int i = 0; i < n; i++)
        {
            while(stk.size() && heights[stk.top()] >= heights[i])stk.pop();
            if(stk.empty()) left[i] = -1;
            else left[i] = stk.top();
            stk.push(i);        
        }

        while(stk.size()) stk.pop();

        //同理,找到右边界
        for(int i = n - 1; i >= 0; i--)
        {
            while(stk.size() && heights[stk.top()] >= heights[i]) stk.pop();
            if(stk.empty()) right[i] = n;
            else right[i] = stk.top();
            stk.push(i);
        }

        int res = 0;
        for(int i = 0; i < n; i++) res = max(res, heights[i] * (right[i] - left[i] - 1));

        return res;
    }
};

LeetCode 239. Sliding Window Maximum

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> res;
        deque<int> q;
        for (int i = 0; i < nums.size(); i ++ )
        {
            if (q.size() && i - k >= q.front()) q.pop_front();
            while (q.size() && nums[q.back()] <= nums[i]) q.pop_back();
            q.push_back(i);
            if (i >= k - 1) res.push_back(nums[q.front()]);
        }
        return res;
    }
};

LeetCode 918. Maximum Sum Circular Subarray

/*

单调栈:查找每个数左侧第一个比它小的数

单调队列:滑动窗口中的最值

*/
class Solution {
public:
    int maxSubarraySumCircular(vector<int>& A) {
        int n = A.size();
        for(int i = 0; i < n; i++) A.push_back(A[i]);
        //因为是个环,所以展开成2×n,这样的话所有的情况都可以枚举的到
        vector<int> sum(n * 2 + 1);
        //然后使用前缀和
        for(int i = 1; i <= n * 2; i++) sum[i] = sum[i-1] + A[i-1];

        int res = INT_MIN;
        //用队列求最值
        deque<int> q;
        q.push_back(0);
        for(int i = 1; i <= n * 2; i++)
        {
            if(q.size() && i - n > q.front()) q.pop_front();
            if(q.size()) res = max(res, sum[i] - sum[q.front()]);
            while(q.size() && sum[q.back()] >= sum[i]) q.pop_back();
            q.push_back(i);
        }               
        return res;
    }
};

基本数据结构

LeetCode 1. Two Sum

class Solution {
public:
    //枚举所有的,如果哈希表中存在则返回
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); i++)
        {
            if(hash.count(target - nums[i])) return {hash[target - nums[i]], i};        
            hash[nums[i]] = i;
        }
        return {-1, -1};
    }
};

LeetCode 187. Repeated DNA Sequences

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        unordered_map<string, int> hash;

        //插入一个字符串
        //统计字符串出现的次数
        vector<string> res;
        for(int i = 0; i < s.size(); i++)
        {
            //这里substr的第二个参数是长度,要注意
            string str = s.substr(i, 10);
            hash[str]++;
            //当然一个字符串可能出现2次以上,我们只记录一次
            if(hash[str] == 2) res.push_back(str);
        }
        return res;
    }
};

LeetCode 706. Design HashMap

class MyHashMap {
public:
    /** Initialize your data structure here. */
    const static int N = 20011;

    vector<list<pair<int,int>>> hash;

    MyHashMap() {
        hash = vector<list<pair<int,int>>>(N);
    }

    list<pair<int,int>>::iterator find(int key)
    {
        int t = key % N;
        auto it = hash[t].begin();
        for (; it != hash[t].end(); it ++ )
            if (it->first == key)
                break;
        return it;
    }

    /** value will always be non-negative. */
    void put(int key, int value) {
        int t = key % N;
        auto it = find(key);
        if (it == hash[t].end())
            hash[t].push_back(make_pair(key, value));
        else
            it->second = value;
    }

    /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
    int get(int key) {
        auto it = find(key);
        if (it == hash[key % N].end())
            return -1;
        return it->second;
    }

    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    void remove(int key) {
        int t = key % N;
        auto it = find(key);
        if (it != hash[t].end())
            hash[t].erase(it);
    }
};

/**
 * Your MyHashMap object will be instantiated and called as such:
 * MyHashMap obj = new MyHashMap();
 * obj.put(key,value);
 * int param_2 = obj.get(key);
 * obj.remove(key);
 */

LeetCode 652. Find Duplicate Subtrees

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int cnt = 0;
    unordered_map<string, int> hash;
    unordered_map<int, int> count;
    vector<TreeNode*> ans;

    //只有前序中序和后序并不能唯一确定一颗树,但是把空节点算上的话就可以
    string dfs(TreeNode* root)
    {
        if(!root) return to_string(hash["#"]);

        //把树进行编码,同时查找           
        auto left = dfs(root->left);
        auto right = dfs(root->right);
        string tree = to_string(root->val) + ',' + left + ',' + right;

        if(!hash.count(tree)) hash[tree] = ++ cnt;
        int t = hash[tree];
        count[t]++;
        if(count[t] == 2) ans.push_back(root);

        return to_string(t);
    }

    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        hash["#"] = ++cnt;
        dfs(root);
        return ans;
    }
};

LeetCode 560. Subarray Sum Equals K

class Solution {
public:

    //这里用到了前缀和和hash表进行查找
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> hash;
        hash[0] = 1;

        int res = 0;
        for(int i = 0, sum = 0; i < nums.size(); i++)
        {
            sum += nums[i];
            res += hash[sum - k];
            hash[sum]++;
        }

        return res;
    }
};

LeetCode 547. Friend Circles

class Solution {
public:
/*
1.合并集合
2.判断两个点是否在同一个集合中
并查集中常用的优化方法:路径压缩,按秩合并
*/
    vector<int> p;

    int find(int x)
    {
        if(p[x] != x) p[x] = find(p[x]);
        return p[x];
    }


    int findCircleNum(vector<vector<int>>& M) {
        int n = M.size();
        for(int i = 0; i < n; i++) p.push_back(i);

        int res = n;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < i; j++)
            {
                if(M[i][j] == 0) continue;
                if(find(i) != find(j))
                {
                    p[find(i)] = find(j);
                    res--;
                }
            }
        }
        return res;
    }
};

LeetCode 684. Redundant Connection

class Solution {
public:

    //查并集,如果新加入的两个点的父节点是同一个,说明他们已经是连接了,再加入就是多余的边
    vector<int> p;

    int find(int x)
    {
        if(p[x] != x) p[x] = find(p[x]);
        return p[x];
    }

    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n = edges.size();

        for(int i = 0; i <= n; i++) p.push_back(i);

        for(auto e : edges)
        {
            int a = e[0], b = e[1];
            if(find(a) == find(b)) return {a, b};
            p[find(a)] = find(b);
        }           

        return {-1, -1};
    }
};

LeetCode 692. Top K Frequent Words

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        //使用哈希表+最小堆
        unordered_map<string, int> hash;
        typedef pair<int, string> PIS;
        priority_queue<PIS> heap;       

        for(auto word : words) hash[word] ++;

        for(auto item : hash)
        {   //一直放到,多了的话把最差的踢出来
            PIS t(-item.second, item.first);
            heap.push(t);
            if(heap.size() > k) heap.pop();
        }

        //取出答案
        vector<string> res(k);
        for(int i = k - 1; i >= 0; i--)
        {
            res[i] = heap.top().second;
            heap.pop();
        }
        return res;
    }
};

LeetCode 295. Find Median from Data Stream

class MedianFinder {
public:

    //这里用到对顶堆
    //如果x大于等于下面的根节点,将其插入上面;
    //如果x小于下面的根节点,将x插入下面
    priority_queue<int, vector<int>, greater<int> > up;
    priority_queue<int> down;

    /** initialize your data structure here. */
    MedianFinder() {

    }

    void addNum(int num) {
        if(down.empty() || num >= down.top()) up.push(num);
        else
        {
            down.push(num);
            up.push(down.top());
            down.pop();     
        }

        if(up.size() > down.size() + 1)
        {
            down.push(up.top());
            up.pop();
        }
    }

    double findMedian() {
        if(down.size() + up.size() & 1) return up.top();
        else return (down.top() + up.top()) / 2.0;
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

LeetCode 352. Data Stream as Disjoint Intervals

class SummaryRanges {
public:

    map<int, int> L, R;

    /** Initialize your data structure here. */
    SummaryRanges() {

    }

    void addNum(int x) {
        if(L.size())
        {
            auto it = L.lower_bound(x);
            if(it != L.end() && it->second <= x) return;        
        }

        int left = L.count(x - 1), right = R.count(x + 1);

        if(left & right)
        {
            R[L[x - 1]] = R[x + 1];
            L[R[x + 1]] = L[x - 1];
            L.erase(x - 1), R.erase(x + 1);
        }
        else if(left)
        {
            R[L[x - 1]] = x;
            L[x] = L[x - 1];
            L.erase(x - 1);
        }       
        else if(right)
        {
            L[R[x + 1]] = x;
            R[x] = R[x + 1];
            R.erase(x + 1);
        }
        else
        {
            R[x] = L[x] = x;
        }       
    }

    vector<vector<int>> getIntervals() {
        vector<vector<int> > res;
        for(auto item : R) res.push_back({item.first, item.second});
        return res;
    }
};

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges* obj = new SummaryRanges();
 * obj->addNum(val);
 * vector<vector<int>> param_2 = obj->getIntervals();
 */

动态规划

LeetCode 53. Maximum Subarray

class Solution {
public:
    //求出所有子段的和的最大值
    //枚举所有的起点和终点
    int maxSubArray(vector<int>& nums) {
        int res = INT_MIN, last = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            int now = max(last, 0) + nums[i];
            res = max(res, now);
            last = now;
        }
        return res;
    }
};

LeetCode 120. Triangle

class Solution {
public:
    int minimumTotal(vector<vector<int>>& nums) {
        int n = nums.size();
        vector<vector<long long>> f(2, vector<long long>(n));
        f[0][0] = nums[0][0];
        for(int i = 1; i < n; i++)
            for(int j = 0; j <= i; j++)
            {
                f[i & 1][j] = INT_MAX;
                if(j > 0) f[i & 1][j] = min(f[i & 1][j], f[i - 1 & 1][j - 1] + nums[i][j]);
                if(j < i) f[i & 1][j] = min(f[i & 1][j], f[i - 1 & 1][j] + nums[i][j]);
            }
        long long res = INT_MAX;
        for(int i = 0; i < n; i++) res = min(res, f[n-1 & 1][i]);
        return res;
    }
};

LeetCode 63. Unique Paths II

class Solution {
public:
    //最后一步可以往下走,最后一步也可往右走
    int uniquePathsWithObstacles(vector<vector<int>>& g) {
        int n = g.size(), m = g[0].size();
        vector<vector<long long>> f(n, vector<long long>(m));
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
            {
                if(g[i][j]) continue;
                if(!i && !j) f[i][j] = 1;
                if(i > 0) f[i][j] += f[i - 1][j];
                if(j > 0) f[i][j] += f[i][j - 1];
            }

        return f[n-1][m-1];
    }
};

LeetCode 91. Decode Ways

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> f(n + 1);
        f[0] = 1;
        for(int i = 1; i <= n; i++)
        {
            if(s[i - 1] != '0') f[i] += f[i-1];
            if(i >= 2)
            {
                int t = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
                if(t >= 10 && t <= 26) f[i] += f[i - 2];
            }
        }
        return f[n];
    }
};

LeetCode 198. House Robber

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n+1), g(n+1);
        for(int i = 1; i <= n; i++)
        {
            f[i] = max(f[i - 1], g[i - 1]);
            g[i] = f[i - 1] + nums[i - 1];
        }
        return max(f[n], g[n]);
    }
};

LeetCode 300. Longest Increasing Subsequence

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n);

        for(int i = 0; i < n; i++)
        {
            f[i] = 1;
            for(int j = 0; j < i; j++)
                if(nums[j] < nums[i])
                    f[i] = max(f[i], f[j] + 1);
        }

        int res = 0;
        for(int i = 0; i < n; i++) res = max(res, f[i]);
        return res;
    }
};

LeetCode 72. Edit Distance

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n = word1.size(), m = word2.size();
        vector<vector<int> > f(n + 1, vector<int>(m + 1));
        for(int i = 0; i <= n; i++) f[i][0] = i;
        for(int i = 0; i <= m; i++) f[0][i] = i;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
            {
                f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;
                f[i][j] = min(f[i][j], f[i - 1][j - 1] + (word1[i - 1] != word2[j - 1]));
            }
        return f[n][m];
    }
};

LeetCode 518. Coin Change 2

class Solution {
public:
    int change(int m, vector<int>& coins) {
        int n = coins.size();
        vector<int> f(m + 1);
        f[0] = 1;
        for(auto c : coins)
            for(int j = c; j <= m; j++)
                f[j] += f[j - c];
        return f[m];
    }
};

LeetCode 664. Strange Printer

class Solution {
public:
    int strangePrinter(string s) {
        if(s.empty()) return 0;
        int n = s.size();
        vector<vector<int>> f(n + 1, vector<int>(n+1));
        for(int len = 1; len <= n; len++)
            for(int l = 0; l + len - 1 < n; l++)
            {
                int r = l + len - 1;
                f[l][r] = f[l + 1][r] + 1;
                for(int k = l + 1; k <= r; k++)
                {
                    if(s[k] == s[l])
                        f[l][r] = min(f[l][r], f[l][k - 1] + f[k + 1][r]);
                }
            }
        return f[0][n - 1];
    }
};

LeetCode 10. Regular Expression Matching

class Solution {
public:
    bool isMatch(string s, string p) {
        int n = s.size(), m = p.size();
        s = ' ' + s, p = ' ' + p;
        vector<vector<bool>> f(n + 1, vector<bool>(m + 1));
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= m; j++)
                if(!i && !j) f[i][j] = true;
                else
                {
                    if(j + 1 <= m && p[j + 1] == '*') continue;
                    if(p[j] != '*')
                    {
                        if(p[j] == '.' || s[i] == p[j])
                            if(i > 0 && j > 0)
                                f[i][j] = f[i - 1][j - 1];
                    }
                    else
                    {
                        if(j >= 2) f[i][j] = f[i][j - 2];
                        if(i > 0 & j > 0)
                        {
                            if(p[j - 1] == '.' || s[i] == p[j - 1])
                                if(f[i - 1][j])
                                    f[i][j] = true;
                        }
                    }
                }
        return f[n][m];
    }
};
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值