二叉树类题目常规解法—Leetcode-thinking_record08

目录

 

预备知识

二叉树的定义

二叉树的构造

理论描述

代码实现 

二叉树的深度遍历

理论描述

代码实现 

二叉树层次遍历 (宽度遍历)

理论描述

代码实现

 

路径之和Ⅱ(Medium)

总体思路

细节设计

代码实现

最近的公共祖先(Medium) 

总体思路

细节设计

求根节点至某节点路径

求根节点至某节点路径(栈存储路径)

 求两路径上最后一个相同的节点

代码实现

二叉树转链表(Medium)

Solve1

总体思想

细节设计

代码实现

Solve2 

总体思想

细节设计

代码实现

侧面观察二叉树(Medium)

总体思路

细节设计

代码实现

 


预备知识

二叉树的定义

二叉树的构造

理论描述

代码实现 

预备知识_二叉树定义.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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值