文章目录
1. 零钱兑换【中等】
题目链接:https://leetcode.cn/problems/coin-change/
 参考题解:https://leetcode.cn/problems/coin-change/solution/322-ling-qian-dui-huan-by-leetcode-solution/
1.1 题目描述
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例1:
示例2:
示例3:
提示:
- 1 <= coins.length <= 12
 - 1 <= coins[i] <= 2^31 - 1
 - 0 <= amount <= 10^4
 
1.2 解题思路
1.3 代码实现
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> ans(amount + 1, amount + 1);
        int len = coins.size();
        ans[0] = 0;
        for(int i = 1; i <= amount; i++) {
            for(int j = 0; j < len; j++) {
                if(coins[j] <= i)
                    ans[i] = min(ans[i], ans[i - coins[j]] + 1);
            }
        }
        return ans[amount] > amount ? -1 : ans[amount];
    }
};
 
2. 最小栈【最小栈】
题目链接:https://leetcode.cn/problems/min-stack/
 参考题解:https://leetcode.cn/problems/min-stack/solution/zui-xiao-zhan-by-leetcode-solution/
2.1 题目描述
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
- MinStack() 初始化堆栈对象。
 - void push(int val) 将元素val推入堆栈。
 - void pop() 删除堆栈顶部的元素。
 - int top() 获取堆栈顶部的元素。
 - int getMin() 获取堆栈中的最小元素。
 
示例1:
提示:
- -2^31 <= val <= 2^31 - 1
 - pop、top 和 getMin 操作总是在 非空栈 上调用
 - push, pop, top, and getMin最多被调用 3 * 10^4 次
 
2.2 解题思路
2.3 代码实现
class MinStack {
public:
    stack<int> stk;
    stack<int> auxStk;
    MinStack() {
        auxStk.push(INT_MAX);
    }
    
    void push(int val) {
        stk.push(val);
        auxStk.push(min(auxStk.top(), val));
    }
    
    void pop() {
        stk.pop();
        auxStk.pop();
    }
    
    int top() {
        return stk.top();
    }
    
    int getMin() {
        return auxStk.top();
    }
};
/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */
 
3. 最长有效括号【困难】
题目链接:https://leetcode.cn/problems/longest-valid-parentheses/
 参考题解:https://leetcode.cn/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode-solution/
3.1 题目描述
给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例1:
示例2:
示例3:
提示:
- 0 <= s.length <= 3 * 10^4
 - s[i] 为 ‘(’ 或 ‘)’
 
3.2 解题思路
3.3 代码实现
class Solution {
public:
    int longestValidParentheses(string s) {
        stack<int> stk;
        stk.push(-1);
        int ans = 0;
        int len = s.length();
        for(int i = 0; i < len; i++) {
            if(s[i] == '(') {
                stk.push(i);
            }
            else {
                stk.pop();
                if(!stk.empty()) {
                    ans = max(ans, i - stk.top());
                }
                else
                    stk.push(i);
            }
        }
        return ans;
    }
};
 
4. 从前序与中序遍历序列构造二叉树【中等】
题目链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
 参考题解:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solution/cong-qian-xu-yu-zhong-xu-bian-li-xu-lie-gou-zao-9/
4.1 题目描述
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例1:
 
示例2:
提示:
- 1 <= preorder.length <= 3000
 - inorder.length == preorder.length
 - -3000 <= preorder[i], inorder[i] <= 3000
 - preorder 和 inorder 均 无重复 元素
 - inorder 均出现在 preorder
 - preorder 保证 为二叉树的前序遍历序列
 - inorder 保证 为二叉树的中序遍历序列
 
4.2 解题思路
4.3 代码实现
/**
 * 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 {
    unordered_map<int, int> find_root;
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder, int pre_start, int pre_end, int in_start, int in_end) {
        if(pre_start > pre_end)
            return nullptr;
        int pre_root = pre_start;
        int in_root = find_root[preorder[pre_root]];
        int left_tree_len = in_root - in_start;
        TreeNode* root = new TreeNode(inorder[in_root]);
        root->left = buildTree(preorder, inorder, pre_root + 1, pre_root + left_tree_len, in_start, in_root - 1);
        root->right = buildTree(preorder, inorder, pre_root + left_tree_len + 1, pre_end, in_root + 1, in_end);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        for(int i = 0; i < inorder.size(); i++)
            find_root[inorder[i]] = i;
        return buildTree(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
    }
};
 
5. 子集【中等】
题目链接:https://leetcode.cn/problems/subsets/
 参考题解:https://leetcode.cn/problems/subsets/solution/zi-ji-by-leetcode-solution/
5.1 题目描述
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例1:
示例2:
提示:
- 1 <= nums.length <= 10
 - -10 <= nums[i] <= 10
 - nums 中的所有元素 互不相同
 
5.2 解题思路
5.3 代码实现
class Solution {
public:
    vector<int> sub;
    vector<vector<int>> ans;
    void chooseNum(vector<int>& nums, int current) {
        if(current == nums.size()) {
            ans.push_back(sub);
            return;
        }
        chooseNum(nums, current + 1);
        sub.push_back(nums[current]);
        chooseNum(nums, current + 1);
        sub.pop_back();
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        chooseNum(nums, 0);
        return ans;
    }
};










