关于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上关于链表的一些高频题,在写代码的过程中总结了链表的一些解题技巧和常见题型. 结点的删除 指定链表中的某个结点,将其从链表中删除. 由于在链表中删除某个结点需要找到该结点的前一 ...
随机推荐
- jquery刷新页面
下面介绍全页面刷新方法:有时候可能会用到 window.location.reload()刷新当前页面. parent.location.reload()刷新父亲对象(用于框架) opener.loc ...
- Android Library Project 使用问题总结
1. 当新建Android Library Project 工程或将已有工程转化为Android Library Project, 如果工程源代码中有如下语句: int id = view.getId ...
- 6to5 – 让你即刻体验 ECMAScript 6 编程
ECMAScript 6 是下一代的 ECMAScript 标准.ECMAScript 6 的目标是让 JavaScript 可以用来编写复杂的应用程序.函数库和代码的自动生成器. ES6 是这门语言 ...
- HTML5 Canvas 高仿逼真 3D 布料图案效果
HTML5 规范引进了很多新特性,其中最令人期待的之一就是 Canvas 元素,HTML5 Canvas 提供了通过 JavaScript 绘制图形的方法,非常强大.下面给大家分享一个 HTML5 C ...
- HTML中input标签的alt属性和title属性的比较
经常用到这两个属性,但是一直没有总结他们的区别.现在我对他们两个的用法做一下总结: 相同点:他们都会飘出一个小浮层,显示文本内容. 不同点: 1.alt只能是元素的属性,而title即可以是元素的属性 ...
- 【初窥javascript奥秘之事件机制】论“点透”与“鬼点击”
前言 最近好好的研究了一番移动设备的点击响应速度,期间不断的被自己坑,最后搞得焦头烂额,就是现在可能还有一些问题,但是过程中感觉自己成长不少, 最后居然感觉对javascript事件机制有了更好的认识 ...
- MySQL索引类型 btree索引和hash索引的区别
来源一 Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 ...
- 一个python线程池的源码解析
python为了方便人们编程高度封装了很多东西,比如进程里的进程池,大大方便了人们编程的效率,但是默认却没有线程池,本人前段时间整理出一个线程池,并进行了简单的解析和注释,本人水平有限,如有错误希望高 ...
- js判断radiobuttonlist的选中值显示/隐藏其它模块
<script> $(function () { var SelectVal = $("input[name='rblGJS']:checked").val(); if ...
- TI的DSP、ST的ARM、Intel的X86浮点性能对比
估计没什么价值,单纯地记录下时间,以便以后查看. TMS320F28335 STM32f030 i3 4170 i3 4170 主频 150MHz 48MHz 3.7GHZ 3.7GHZ IDE ...