关于Leetcode上二叉树的算法总结
二叉树,结构很简单,只是比单链表复杂了那么一丢丢而已。我们先来看看它们结点上的差异:
/* 单链表的结构 */
struct SingleList{
int element;
struct SingleList *next;
};
/* 二叉树的结构 */
struct BinaryTree{
int element;
struct BinaryTree *left;
struct BinaryTree *right;
};
根据以上两个结构,我们不难发现,单链表的结点只有一个指向下一结点的指针,而二叉树中有两个。也就是说单链表每个结点只有一个子节点,而二叉树有两个子节点(其中一个可能为NULL)。了解了这一点的区别,我们就知道:基于二叉树的算法比基于单链表的算法差异就是每次遍历一个结点之后,需要遍历两个子节点,而单链表只需要遍历一个子节点。
这就引出了2种遍历的方法:广度优先遍历(BFS)和深度优先遍历(DFS)。
对于单链表来说,BFS和DFS是一样的,因为每个节点只有一个子节点,每次遍历下一个节点只有一种选择;但是二叉树每个节点有两个子节点,也就是说遍历的顺序既可以遍历它的子节点(无论左节点还是右结点都是DFS),也可以遍历它的兄弟结点。如果是每次先遍历子节点那么就是DFS;每次先遍历兄弟结点,就是BFS。
DFS采用栈结构,博主这里用的是递归来实现栈,当然大家也可以用stack来实现;BFS采用的是队列queue。
void dfs(BinaryTree *root){
if(NULL == root)
return ;
dfs(root->left);
dfs(root->right);
}
void bfs(BinaryTree *root){
if(NULL == root)
return ;
queue<BinaryTree *> que;
que.push();
while(!que.empty()){
BinaryTree *pNode = que.front();
que.pop();
if(pNode->left)
que.push(pNode->left);
if(pNode->right)
que.push(pNode->right);
}
}
关于树的一些算法中,DFS和BFS一般都适用,但是当涉及到根到叶的路径这类问题时,最好还是用DFS来实现。如下所示:
1、给一棵二叉树和一个值Sum,求出所有从根到叶子的值等于Sum的所有路径。
思路:深度优先搜索(DFS),然后把从跟开始每次访问一个结点就把该结点添加到一个vec的最后位置,并把sum减去当前借点的值后传递给下一个节点,当一个结点的左右孩子都为NULL,并且值等于sum时,就说明该节点是叶子节点,并且从根结点到该节点的路径和为Sum,把vec,添加到res中;每次返回时,需要把vec中的最后一个值删除,因为每个节点有两个子节点,从根节点到左孩子的叶子的路径与到右孩子叶子的路径是不同的,所有每次访问完左孩子或者右孩子需要把孩子的值从vec中删除。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
private:
vector<vector<int>> res;
vector<int> vec;
void _pathSum(TreeNode* root, int sum){
if(root == NULL)
return ;
vec.push_back(root->val);
if(root->left == NULL && root->right == NULL && sum == root->val){
res.push_back(vec);
return ;
}
_pathSum(root->left, sum-root->val);
if(root->left)
vec.pop_back();
_pathSum(root->right, sum-root->val);
if(root->right)
vec.pop_back();
}
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
if(NULL == root)
return res;
_pathSum(root, sum);
return res;
}
};
2、转化二叉树
把二叉树:
/ \
/ \ / \
转化成
/ \
/ \ / \
思路:这个既可以用DFS也可以用BFS,也就是遍历每个节点,然后将它们的左右孩子互换即可。这里采用BFS来实现:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(NULL == root)
return NULL;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
TreeNode* pChild = que.front();
que.pop();
TreeNode* pNode = pChild->left;
pChild->left = pChild->right;
pChild->right = pNode;
if(pChild->left)
que.push(pChild->left);
if(pChild->right)
que.push(pChild->right);
}
return root;
}
};
3、总结
只要掌握了DFS和BFS的思想,其它关于二叉树的算法基本上都是类似的,必要的时候通过画图来让自己感性认识一下也是极好的。
关于Leetcode上的题目代码:https://github.com/whc2uestc/onlineJudge/tree/master/leetCode
版权所有,欢迎转载,转载请注明出处。
关于Leetcode上二叉树的算法总结的更多相关文章
- LeetCode:二叉树的后序遍历【145】
LeetCode:二叉树的后序遍历[145] 题目描述 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很 ...
- LeetCode:二叉树的层次遍历||【107】
LeetCode:二叉树的层次遍历||[107] 题目描述 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 例如:给定二叉树 [3,9,2 ...
- LeetCode:二叉树剪枝【814】
LeetCode:二叉树剪枝[814] 题目描述 给定二叉树根结点 root ,此外树的每个结点的值要么是 0,要么是 1. 返回移除了所有不包含 1 的子树的原二叉树. ( 节点 X 的子树为 X ...
- Leetcode 297.二叉树的序列化和反序列化
二叉树地序列化和反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据. ...
- 别再埋头刷LeetCode之:北美算法面试的题目分类,按类型和规律刷题,事半功倍
算法面试过程中,题目类型多,数量大.大家都不可避免的会在LeetCode上进行训练.但问题是,题目杂,而且已经超过1300道题. 全部刷完且掌握,不是一件容易的事情.那我们应该怎么办呢?找规律,总结才 ...
- Java实现 LeetCode 297 二叉树的序列化与反序列化
297. 二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得 ...
- LeetCode解题记录(贪心算法)(二)
1. 前言 由于后面还有很多题型要写,贪心算法目前可能就到此为止了,上一篇博客的地址为 LeetCode解题记录(贪心算法)(一) 下面正式开始我们的刷题之旅 2. 贪心 763. 划分字母区间(中等 ...
- 利用Mahout实现在Hadoop上运行K-Means算法
利用Mahout实现在Hadoop上运行K-Means算法 一.介绍Mahout Mahout是Apache下的开源机器学习软件包,目前实现的机器学习算法主要包含有协同过滤/推荐引擎,聚类和分类三个部 ...
- 关于LeetCode上链表题目的一些trick
最近在刷leetcode上关于链表的一些高频题,在写代码的过程中总结了链表的一些解题技巧和常见题型. 结点的删除 指定链表中的某个结点,将其从链表中删除. 由于在链表中删除某个结点需要找到该结点的前一 ...
随机推荐
- mysql本地可以访问 网络不能访问
远程登陆数据库的时候出现了下面出错信息: ERROR 2003 (HY000): Can't connect to MySQL server on 'xxx.xxx.xxx.xxx', 经过今天下午的 ...
- Lucene.net站内搜索—6、站内搜索第二版
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- mesos 学习笔记1 -- mesos安装和配置
参考资料: 官方文档:http://mesos.apache.org/documentation 中文翻译:http://mesos.mydoc.io/ GitHub:https://github.c ...
- javascript中数组的常用方法
数组的基本方法如下 1.concat() 2.join() 3.pop() 4.push() 5.reverse() 6.shift() 7.sort() 8.splice() 9.toString( ...
- 腾讯用过的插件jQuery twentytwenty 效果对比
在线实例 左右对比 上下对比 使用方法 <div class="twentytwenty-container"> <img src="/api/ ...
- js删除数组中的'NaN'
js中的NaN不和任何值相等,包括自身. 所以可以使用x!=x来判断x是否是NaN,当且仅当x为NaN时,表达式的结果为true. NaN != NaN //true 可以依此删除数组中的'NaN'. ...
- 100个高质量Java开发者博客
ImportNew注:原文中还没有100个.作者希望大家一起来推荐高质量的Java开发博客,然后不段补充到这个列表.欢迎你也参与推荐优质的Java开发博客.(声明一下:我们的数学不是体育老师教的!:) ...
- 直接拿来用!十大Material Design开源项目
来自:http://www.csdn.net/article/2014-11-21/2822753-material-design-libs/1 介于拟物和扁平之间的Material Design自面 ...
- AndRoid studio创建APP图标
打开---File----New----Image asset 注意:在design页面可能没有image asset选项!必须在其他编辑页面! 这就打开了图标设置页面,找到自己想要的图标就好!下面框 ...
- 打印完整URL
if(requestDictionary != nil) { //添加参数,将参数拼接在url后面 NSMutableString *paramsString = [NSMutableString s ...