之前收藏了极客时间的算法训练营3期 共21课,计划每一课写博客来记录学习,主要形式为
方法类型1
题1
题解
题2
题解
方法类型2
题1
题解
……
题目大体来自leetcode 和 acwing
主要记录和理解代码,所以基本完全搬运了视频题解代码,
个人学习感受体现在大致思路的总结和注释上。
一、递归
1.子集
class Solution {
public:
vector> subsets(vector& nums) {
n = nums.size();
recur(nums, 0);
return ans;
}
private:
vector> ans;
vector chosen;
int n;
void recur(vector& nums, int i) {
if (i == n) {
ans.push_back(chosen);
return;
}
//向两个分支递归下去
recur(nums, i + 1);
chosen.push_back(nums[i]);
recur(nums, i + 1);
chosen.pop_back();
}
};
2.组合
剪枝的应用,边界判定
class Solution {
public:
vector> combine(int n, int k) {
this->n = n;
this->k = k;
recur(1);
return ans;
}
private:
int n;
int k;
vector> ans;
vector chosen;
void recur(int i) {
//由于到了n点,需要确定是不是要n,所以为n+1;
if (i == n + 1) {
if (chosen.size() == k)
ans.push_back(chosen);
return;
}
//剩余没有可能符合条件的去掉
if (chosen.size() > k || (n - i + 1) + chosen.size() < k) return;
recur(i + 1);
chosen.push_back(i);
recur(i + 1);
chosen.pop_back();
}
};
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 {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) return nullptr;
TreeNode* tmp;
tmp = root->left;
root->left = root->right;
root->right = tmp;
invertTree(root->left);
invertTree(root->right);
return root;
}
};
4.验证二叉搜索树
单纯的验证左右孩子的值是不行的,要注意左右子树所有结点都要小于父亲结点值。
/**
* 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:
bool isValidBST(TreeNode* root) {
//对每一个根节点限定范围,别直接考虑左右子树
return check(root,-(1ll << 32),1ll << 32);
}
private:
bool check(TreeNode* root, long long rangeLeft, long long rangeRight) {
if (root == nullptr) return true;
if (root->val < rangeRight && root->val > rangeLeft)
return check(root->left, rangeLeft, root->val) && check(root->right, root->val, rangeRight);
return false;
}
};
二、分治
1.括号生成
分为(A)B,讨论A,B两个子集。范围为0到n-1
class Solution {
public:
vector generateParenthesis(int n) {
if (n == 0) return {""};
if (store.find(n) != store.end()) return store[n];
vector ans;
for(int i = 1; i <= n; i++) {
vector A = generateParenthesis(n - i);
vector B = generateParenthesis(i - 1);
for(string& a : A)
for(string& b : B)
ans.push_back("(" + b + ")" + a);
}
store[n] = ans;
return ans;
}
private:
unordered_map> store;
};