记录算法基础题思路:
step1:
求路径之和二:https://leetcode-cn.com/problems/path-sum-ii/
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
/* 利用一个数组记录前序遍历过程路径每个值,并用sum记录路径和,在遍历到叶子节点的时候校验 */
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int>> res;
vector <int> path;
int path_sum = 0;
traveral_pre(root, sum, path_sum, path, res);
return res;
}
void traveral_pre(TreeNode* root, int sum, int path_sum,
vector <int> &path, vector<vector<int>> &res) {
if (root == NULL) {
return;
}
path.push_back(root->val);
path_sum += root->val;
if (root->left == NULL && root->right == NULL && path_sum == sum) {
res.push_back(path);
}
traveral_pre(root->left, sum, path_sum, path, res);
traveral_pre(root->right, sum, path_sum, path, res);
path_sum -= root->val;
path.pop_back();
}
二叉树节点公共祖先:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/submissions/
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
private:
TreeNode * res = NULL;
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
/* 后序遍历,如果某个节点的子树 根+左子树+右子树 能找到两个节点,说明此根子树为公共祖先 */
if (root == NULL) {
return NULL;
}
travel_find_node(root, p, q);
return res;
}
bool travel_find_node(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL) {
return false;
}
bool left_find = travel_find_node(root->left, p, q);
bool right_find = travel_find_node(root->right, p, q);
bool root_find = (root == p || root == q) ? true : false;
if (left_find + right_find + root_find >= 2) {
res = root;
}
return left_find + right_find + root_find > 0 ? true : false;
}
二叉树转化链表:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/submissions/
给定一个二叉树,原地将它展开为链表
public:
void flatten(TreeNode* root) {
/* 后序遍历,先处理左子树,再处理右子树,然后把左子树插入右子树分支 */
if (root == NULL) {
return;
}
flatten(root->left); /* 递归左子树 */
flatten(root->right); /* 递归右子树 */
/* 转化子树链表 */
TreeNode *tmp = root->right;
root->right = root->left; /* 把原来左子树放到右子树 */
root->left = NULL;
while (root->right != NULL) { /* 找到最原来左子树末端的 */
root = root->right;
}
root->right = tmp; /* 追加原来右子树 到 末端 */
}
二叉树右视图 https://leetcode-cn.com/problems/binary-tree-right-side-view/submissions/
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
/* 层次遍历 利用队列,每层最后一个元素就是右边元素 */
/* 每层次遍历的时候 先看队列中的元素个数,就为当前层的数量,取最后一个 */
vector<int> res;
if (root == NULL) {
return res;
}
queue <TreeNode*> que;
que.push(root);
while (!que.empty()) {
int level_num = que.size();
for (int i = 0; i < level_num; i++) {
TreeNode *node = que.front();
que.pop();
/* 层中每个node,最后一个记录 */
if (i == level_num - 1) {
res.push_back(node->val);
}
if (node->left != NULL) {
que.push(node->left);
}
if (node->right != NULL) {
que.push(node->right);
}
}
}
return res;
课程安排:https://leetcode-cn.com/problems/course-schedule/submissions/
你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
示例:
输入: 2, [[1,0]]
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<int> in_degree(numCourses, 0);
vector<vector<int>> node_list(numCourses, vector<int>());
for (auto i : prerequisites) {
in_degree[i[0]]++; /* 入度更新 */
node_list[i[1]].push_back(i[0]); /* 邻接点更新 */
}
queue<int> que;
/* 将入度为 0 的结点放入队列 */
for (auto i = 0; i < in_degree.size(); i++) {
if (in_degree[i] == 0) que.push(i);
}
vector<int> res;
while (!que.empty()) {
auto q = que.front();
que.pop();
/* 取出入度为0的顶点,放入res, 然后将该点为入边邻接点的元素度-1 */
res.push_back(q);
for (auto j : node_list[q]) {
in_degree[j]--;
if (in_degree[j] == 0) que.push(j);
}
}
return res.size() == numCourses;
}