二叉树,结构很简单,只是比单链表复杂了那么一丢丢而已。我们先来看看它们结点上的差异:

/* 单链表的结构 */
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上二叉树的算法总结的更多相关文章

  1. LeetCode:二叉树的后序遍历【145】

    LeetCode:二叉树的后序遍历[145] 题目描述 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很 ...

  2. LeetCode:二叉树的层次遍历||【107】

    LeetCode:二叉树的层次遍历||[107] 题目描述 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 例如:给定二叉树 [3,9,2 ...

  3. LeetCode:二叉树剪枝【814】

    LeetCode:二叉树剪枝[814] 题目描述 给定二叉树根结点 root ,此外树的每个结点的值要么是 0,要么是 1. 返回移除了所有不包含 1 的子树的原二叉树. ( 节点 X 的子树为 X ...

  4. Leetcode 297.二叉树的序列化和反序列化

    二叉树地序列化和反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据. ...

  5. 别再埋头刷LeetCode之:北美算法面试的题目分类,按类型和规律刷题,事半功倍

    算法面试过程中,题目类型多,数量大.大家都不可避免的会在LeetCode上进行训练.但问题是,题目杂,而且已经超过1300道题. 全部刷完且掌握,不是一件容易的事情.那我们应该怎么办呢?找规律,总结才 ...

  6. Java实现 LeetCode 297 二叉树的序列化与反序列化

    297. 二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得 ...

  7. LeetCode解题记录(贪心算法)(二)

    1. 前言 由于后面还有很多题型要写,贪心算法目前可能就到此为止了,上一篇博客的地址为 LeetCode解题记录(贪心算法)(一) 下面正式开始我们的刷题之旅 2. 贪心 763. 划分字母区间(中等 ...

  8. 利用Mahout实现在Hadoop上运行K-Means算法

    利用Mahout实现在Hadoop上运行K-Means算法 一.介绍Mahout Mahout是Apache下的开源机器学习软件包,目前实现的机器学习算法主要包含有协同过滤/推荐引擎,聚类和分类三个部 ...

  9. 关于LeetCode上链表题目的一些trick

    最近在刷leetcode上关于链表的一些高频题,在写代码的过程中总结了链表的一些解题技巧和常见题型. 结点的删除 指定链表中的某个结点,将其从链表中删除. 由于在链表中删除某个结点需要找到该结点的前一 ...

随机推荐

  1. 用SQL语句添加删除修改字段_常用SQL

    1.增加字段     alter table docdsp     add dspcodechar(200)2.删除字段     ALTER TABLE table_NAME DROP COLUMNc ...

  2. HTTP 方法:GET 对比 POST

    什么是 HTTP? 超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信. HTTP 的工作方式是客户机与服务器之间的请求-应答协议. web 浏览器可能是客户端,而计算机上的网络应用程 ...

  3. 我们为什么要配置CATALINA_HOME环境变量

    用文本编辑工具打开用于启动Tomcat的批处理文件startup.bat,仔细阅读.在这个文件中,首先判断CATALINA_HOME环境变量是否为空,如果为空,就将当前目录设为CATALINA_HOM ...

  4. java集合-hashCode

    hashCode 的作用 在 Java 集合中有两类,一类是 List,一类是 Set 他们之间的区别就在于 List 集合中的元素师有序的,且可以重复,而 Set 集合中元素是无序不可重复的.对于 ...

  5. Java基础学习小记--多态

    题外话:总结了多年的学习心得,不得不说,睡眠是一个学习者的必需品!所谓"早起毁一天"不是没有道理哪,特别对Coders来说,有几天不是加班到夜里.好吧,我承认对于初学Java的我, ...

  6. Webform(分页与组合查询配合使用)

    1.封装实体类 2.写查询方法 //SubjectData类 public List<Subject> Select(string name) { List<Subject> ...

  7. (1)RGB-D SLAM系列- 工具篇(硬件+关键技术)

    /*************************************************************************************************** ...

  8. C#实现类似"hello $world"的格式化字符串方法

    C#自带的string.Format可以格式化字符串,但是还是不太好用,由于格式的字符占位符都是数字,当数目较多时容易混淆.其实可以扩展string的方法,让C#的字符串具备其他的方法,下面介绍一个实 ...

  9. CSS基础教程 -- 媒体查询屏幕适配

    响应式布局 Media Query 的使用方法 在上例中, 我们使用Media Queries来根据3种不同尺寸的窗口使用3种不同的样式.通过不同的媒体类型和条件定义样式表规则,媒体查询让CSS可以更 ...

  10. spring-hellow word

          在大三的时候开了一门JAVAEE SSH框架,属于软件方向选修课程,虽然本人是搞硬件的,但是也选了这么课程,因为我在想有一天物联网也会走上大门户的,所以果断去蹭课了,时至今日,重新拾起来, ...