目录
预备知识
二叉树的定义
二叉树的构造
理论描述
代码实现
预备知识_二叉树定义.cpp
#include <stdio.h>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
void preorder_print(TreeNode *node,int layer){
if (!node){
return;
}
for (int i = 0; i < layer; i++){
printf("-----");
}
printf("[%d]\n", node->val);
preorder_print(node->left, layer + 1);
preorder_print(node->right, layer + 1);
}
int main(){
TreeNode a(1);
TreeNode b(2);
TreeNode c(5);
TreeNode d(3);
TreeNode e(4);
TreeNode f(6);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.right = &f;
preorder_print(&a, 0);
return 0;
}
二叉树的深度遍历
理论描述
代码实现
预备知识_二叉树深度遍历.cpp
#include <stdio.h>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
void traversal(TreeNode *node){
if (!node){
return;
}
traversal(node->left);
traversal(node->right);
}
void traversal_print1(TreeNode *node,int layer){
if (!node){
return;
}
traversal_print1(node->left, layer + 1);
for (int i = 0; i < layer; i++){
printf("-----");
}
printf("[%d]\n", node->val);
traversal_print1(node->right, layer + 1);
}
void traversal_print2(TreeNode *node,int layer){
if (!node){
return;
}
traversal_print2(node->left, layer + 1);
traversal_print2(node->right, layer + 1);
for (int i = 0; i < layer; i++){
printf("-----");
}
printf("[%d]\n", node->val);
}
void traversal_print3(TreeNode *node,int layer){
if (!node){
return;
}
for (int i = 0; i < layer; i++){
printf("-----");
}
printf("[%d]\n", node->val);
traversal_print3(node->left, layer + 1);
traversal_print3(node->right, layer + 1);
}
int main(){
TreeNode a(1);
TreeNode b(2);
TreeNode c(5);
TreeNode d(3);
TreeNode e(4);
TreeNode f(6);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.right = &f;
traversal_print1(&a, 0);
printf("\n");
traversal_print2(&a, 0);
printf("\n");
traversal_print3(&a, 0);
printf("\n");
return 0;
}
二叉树层次遍历 (宽度遍历)
理论描述
代码实现
#include <stdio.h>
#include <vector>
#include <queue>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
void BFS_print(TreeNode* root){
std::queue<TreeNode *> Q;
Q.push(root);
while(!Q.empty()){
TreeNode *node = Q.front();
Q.pop();
printf("[%d]\n", node->val);
if (node->left){
Q.push(node->left);
}
if (node->right){
Q.push(node->right);
}
}
}
int main(){
TreeNode a(1);
TreeNode b(2);
TreeNode c(5);
TreeNode d(3);
TreeNode e(4);
TreeNode f(6);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.right = &f;
BFS_print(&a);
return 0;
}
路径之和Ⅱ(Medium)
LeetCode 113.Path Sum II
给定一个二叉树与整数sum,找出所有从根节点到叶结点的路径,这些路径上的节点值累加和为sum.
总体思路
细节设计
代码实现
#include <stdio.h>
#include <vector>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
std::vector<std::vector<int> > pathSum(TreeNode* root, int sum) {
std::vector<std::vector<int> > result;
std::vector<int> path;
int path_value = 0;
preorder(root, path_value, sum, path, result);
return result;
}
private:
void preorder(TreeNode *node, int &path_value, int sum,
std::vector<int> &path,
std::vector<std::vector<int> > &result){
if (!node){
return;
}
path_value += node->val;
path.push_back(node->val);
if (!node->left && !node->right && path_value == sum){
result.push_back(path);
}
preorder(node->left, path_value, sum, path, result);
preorder(node->right, path_value, sum, path, result);
path_value -= node->val;
path.pop_back();
}
};
int main(){
TreeNode a(5);
TreeNode b(4);
TreeNode c(8);
TreeNode d(11);
TreeNode e(13);
TreeNode f(4);
TreeNode g(7);
TreeNode h(2);
TreeNode x(5);
TreeNode y(1);
a.left = &b;
a.right = &c;
b.left = &d;
c.left = &e;
c.right = &f;
d.left = &g;
d.right = &h;
f.left = &x;
f.right = &y;
Solution solve;
std::vector<std::vector<int> > result = solve.pathSum(&a, 22);
for (int i = 0; i < result.size(); i++){
for (int j = 0; j < result[i].size(); j++){
printf("[%d]", result[i][j]);
}
printf("\n");
}
return 0;
}
最近的公共祖先(Medium)
LeetCode 236.Lowest Common Ancestor of a Binary Tree
已知二叉树,求二叉树种给定的两个节点的最近公共祖先。
最近公共祖先:两节点v与w的最近公共祖先u,满足在树上最低(离根最远),且v,w两个节点都是u的子孙。
总体思路
细节设计
求根节点至某节点路径
求根节点至某节点路径(栈存储路径)
求两路径上最后一个相同的节点
代码实现
#include <stdio.h>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
#include <vector>
#include <set>
void preorder(TreeNode* node,
TreeNode *search,
std::vector<TreeNode*> &path,
std::vector<TreeNode*> &result,
int &finish){
if (!node || finish){
return;
}
path.push_back(node);
if (node == search){
finish = 1;
result = path;
}
preorder(node->left, search, path, result, finish);
preorder(node->right, search, path, result, finish);
path.pop_back();
}
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
std::vector<TreeNode*> path;
std::vector<TreeNode*> node_p_path;
std::vector<TreeNode*> node_q_path;
int finish = 0;
preorder(root, p, path, node_p_path, finish);
path.clear();
finish = 0;
preorder(root, q, path, node_q_path, finish);
int path_len = 0;
if (node_p_path.size() < node_q_path.size()){
path_len = node_p_path.size();
}
else{
path_len = node_q_path.size();
}
TreeNode *result = 0;
for (int i = 0; i < path_len; i++){
if (node_p_path[i] == node_q_path[i]){
result = node_p_path[i];
}
}
return result;
}
};
int main(){
TreeNode a(3);
TreeNode b(5);
TreeNode c(1);
TreeNode d(6);
TreeNode e(2);
TreeNode f(0);
TreeNode x(8);
TreeNode y(7);
TreeNode z(4);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
c.right = &x;
e.left = &y;
e.right = &z;
Solution solve;
TreeNode *result = solve.lowestCommonAncestor(&a, &b, &f);
printf("lowestCommonAncestor = %d\n", result->val);
result = solve.lowestCommonAncestor(&a, &d, &z);
printf("lowestCommonAncestor = %d\n", result->val);
result = solve.lowestCommonAncestor(&a, &b, &y);
printf("lowestCommonAncestor = %d\n", result->val);
return 0;
}
二叉树转链表(Medium)
LeetCode 114.Flatten Binary Tree to Linked List
给定一个二叉树,将该二叉树就地(in-place)转换为单链表。单链表中节点顺序为二叉树前序遍历顺序。
Solve1
总体思想
细节设计
代码实现
#include <stdio.h>
#include <vector>
struct GraphNode{
int label;
std::vector<GraphNode *> neighbors;
GraphNode(int x) : label(x) {};
};
bool DFS_graph(GraphNode *node, std::vector<int> &visit){
visit[node->label] = 0;
for (int i = 0; i < node->neighbors.size(); i++){
if (visit[node->neighbors[i]->label] == -1){
if (DFS_graph(node->neighbors[i], visit) == 0){
return false;
}
}
else if (visit[node->neighbors[i]->label] == 0){
return false;
}
}
visit[node->label] = 1;
return true;
}
class Solution {
public:
bool canFinish(int numCourses,
std::vector<std::pair<int, int> >& prerequisites) {
std::vector<GraphNode*> graph;
std::vector<int> visit;
for (int i = 0; i < numCourses; i++){
graph.push_back(new GraphNode(i));
visit.push_back(-1);
}
for (int i = 0; i < prerequisites.size(); i++){
GraphNode *begin = graph[prerequisites[i].second];
GraphNode *end = graph[prerequisites[i].first];
begin->neighbors.push_back(end);
}
for (int i = 0; i < graph.size(); i++){
if (visit[i] == -1 && !DFS_graph(graph[i], visit)){
return false;
}
}
for (int i = 0; i < numCourses; i++){
delete graph[i];
}
return true;
}
};
int main(){
std::vector<std::pair<int, int> > prerequisites;
prerequisites.push_back(std::make_pair(1, 0));
prerequisites.push_back(std::make_pair(2, 0));
prerequisites.push_back(std::make_pair(3, 1));
prerequisites.push_back(std::make_pair(3, 2));
Solution solve;
printf("%d\n", solve.canFinish(4, prerequisites));
return 0;
}
Solve2
总体思想
细节设计
代码实现
#include <stdio.h>
#include <vector>
#include <queue>
struct GraphNode{
int label;
std::vector<GraphNode *> neighbors;
GraphNode(int x) : label(x) {};
};
class Solution {
public:
bool canFinish(int numCourses,
std::vector<std::pair<int, int> >& prerequisites) {
std::vector<GraphNode*> graph;
std::vector<int> degree;
for (int i = 0; i < numCourses; i++){
degree.push_back(0);
graph.push_back(new GraphNode(i));
}
for (int i = 0; i < prerequisites.size(); i++){
GraphNode *begin = graph[prerequisites[i].second];
GraphNode *end = graph[prerequisites[i].first];
begin->neighbors.push_back(end);
degree[prerequisites[i].first]++;
}
std::queue<GraphNode *> Q;
for (int i = 0; i < numCourses; i++){
if (degree[i] == 0){
Q.push(graph[i]);
}
}
while(!Q.empty()){
GraphNode *node = Q.front();
Q.pop();
for (int i = 0; i < node->neighbors.size(); i++){
degree[node->neighbors[i]->label]--;
if (degree[node->neighbors[i]->label] == 0){
Q.push(node->neighbors[i]);
}
}
}
for (int i = 0; i < graph.size(); i++){
delete graph[i];
}
for (int i = 0; i < degree.size(); i++){
if (degree[i]){
return false;
}
}
return true;
}
};
int main(){
std::vector<std::pair<int, int> > prerequisites;
prerequisites.push_back(std::make_pair(1, 0));
prerequisites.push_back(std::make_pair(2, 0));
prerequisites.push_back(std::make_pair(3, 1));
prerequisites.push_back(std::make_pair(3, 2));
Solution solve;
printf("%d\n", solve.canFinish(4, prerequisites));
return 0;
}
侧面观察二叉树(Medium)
LeetCode 199.Binary Tree Right Side View
给定一个二叉树,假设从该二叉树的右侧观察它,将观察到的节点按照从上到下的顺序输出。
总体思路
细节设计
代码实现
#include <stdio.h>
#include <vector>
#include <queue>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
std::vector<int> rightSideView(TreeNode* root) {
std::vector<int> view;
std::queue<std::pair<TreeNode *, int> > Q;
if (root){
Q.push(std::make_pair(root, 0));
}
while(!Q.empty()){
TreeNode *node = Q.front().first;
int depth = Q.front().second;
Q.pop();
if (view.size() == depth){
view.push_back(node->val);
}
else{
view[depth] = node->val;
}
if (node->left){
Q.push(std::make_pair(node->left, depth + 1));
}
if (node->right){
Q.push(std::make_pair(node->right, depth + 1));
}
}
return view;
}
};
int main(){
TreeNode a(1);
TreeNode b(2);
TreeNode c(5);
TreeNode d(3);
TreeNode e(4);
TreeNode f(6);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.right = &f;
Solution solve;
std::vector<int> result = solve.rightSideView(&a);
for (int i = 0; i < result.size(); i++){
printf("[%d]\n", result[i]);
}
return 0;
}