二叉树的最大深度

二叉树,所以可以考虑用递归来做。由于根节点已经算过了,所以需要加上1;每次返回都是以递归时的节点作为根节点进行判断的最大深度。还是比较好理解,代码如下:

/**
* 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:
int maxDepth(TreeNode* root) {
if(root==NULL) return 0;
int LeftSize=1+maxDepth(root->left);
int RightSize=1+maxDepth(root->right);
return max(LeftSize,RightSize);
}
};

在网上还看到了有人用队列来做,附代码如下:

class Solution {
public:
int maxDepth(TreeNode* root) {
if(!root) return 0;
int res=0;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
++res;
int n=q.size();
for(int i=0;i<n;++i)
{
TreeNode *t=q.front();q.pop();
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
}
return res;
}
};

这个方法也是非常的巧妙!利用队列来存储每一个要处理的节点,处理之前先记一次数res,处理时从队列中拿出来,专门处理这个节点,如果这个节点是子节点,不执行操作;如果不为子节点,在队列中存储它的左右节点,在下一次循环中先取左节点再取右节点进行处理。

验证二叉搜索树

这道题没什么思路,开始想用和上一道题一样的递归的解法,发现不得行。直接看了大神的代码:

// Recursion without inorder traversal
class Solution {
public:
bool isValidBST(TreeNode *root) {
return isValidBST(root, LONG_MIN, LONG_MAX);
}
bool isValidBST(TreeNode *root, long mn, long mx) {
if (!root) return true;
if (root->val <= mn || root->val >= mx) return false;
return isValidBST(root->left, mn, root->val) && isValidBST(root->right, root->val, mx);
}
};

他这样的解法是重载了一个新的isValidBST函数,用自己需要的参数进行判断(还有此等操作??!!)然后利用return isValidBST(root->left, mn, root->val) && isValidBST(root->right, root->val, mx);进行递归判断,而判断语句也写得非常的巧妙if (root->val <= mn || root->val >= mx) return false;。首先每次递归的时候会判断语句中的两个判断条件的一个是否满足条件,就是判断root->left与root进行比较或者将root->right与root进行比较,而另外一个条件则是由于传送了参数LONG_MIN,与LONG_MAX,所以这部分条件是始终满足的。而实现这么巧妙的一个判断语句能分情况的处理条件是和我们传送参数的顺序有关的,比如isValidBST(root->left, mn, root->val)isValidBST(root->right, root->val, mx)两个参数的顺序不一致,所以可以实现这么巧妙的变化。

此外网上还有其他解法:

public class Solution {
/**
* @param root: The root of binary tree.
* @return: True if the binary tree is BST, or false
*/
public int lastVal = Integer.MAX_VALUE;
public boolean firstNode = true;
public boolean isValidBST(TreeNode root) {
// write your code here
if(root == null){
return true;
}
if(!isValidBST(root.left)){
return false;
}
if(!firstNode && lastVal >= root.val){
return false;
}
//此时 root.val>=lastval 是右子树
firstNode = false;
lastVal = root.val;
if(!isValidBST(root.right)){
return false;
}
return true;
}
}

这段代码里是用lastVal来存储目前处理的上一个根节点的值,firstNode来判断现在处理的是左子树还是右子树。这道题还是挺有难度的。

对称二叉树

利用队列,检测左节点的左节点与右节点的右节点、左节点的右节点与右节点的左节点是否相等。循环的条件为队列中有元素,没有元素就代表所有结点都判断完了,返回true;中途如果有不满足判断条件,就直接返回false。值得一提的是,while循环中创建了两个新节点node1与node2,分别存储各自根节点的左或右子节点,看代码就应该比较好理解:

/**
* 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:
bool isSymmetric(TreeNode* root) {
if(root==NULL) return true;
queue<TreeNode *>q1,q2;
q1.push(root->left);
q2.push(root->right); while(!q1.empty() && !q2.empty())
{
TreeNode *node1=q1.front();
TreeNode *node2=q2.front();
q1.pop();q2.pop();
if((node1==NULL && node2!=NULL) || (node1!=NULL && node2==NULL))
return false;
if(node1!=NULL && node2!=NULL)
{
if(node1->val!=node2->val)
return false;
else
{
q1.push(node1->left);
q2.push(node2->right);
q1.push(node1->right);
q2.push(node2->left);
}
}
}
return true;
}
};

然后,这里再贴出大神的重载函数代码:

class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(!root) return true;
return isSymmetric(root->left,root->right);
}
bool isSymmetric(TreeNode *left,TreeNode *right){
if(!left && !right) return true;
if((left && !right) || (!left && right) || (left->val!=right->val)) return false;
return isSymmetric(left->left,right->right) && isSymmetric(left->right,right->left);
}
};

二叉树的层次遍历

    /**
* 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:
//二叉树层次遍历 通过队列BFS广度优先搜索
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
queue<TreeNode*>q;
vector<int> level; //每层结果
int size,i;
TreeNode* p; if(root==NULL) return result;
q.push(root); //入队
while(!q.empty()) {
//队列中有几个元素就依次遍历每个元素的左右结点
level.clear();
size=q.size();
for(i=0; i<size; i++) {
p=q.front(); //队首元素值赋给p
q.pop(); //出队
level.push_back(p->val);
if(p->left) { //依次压入左右结点元素
q.push(p->left);
}
if(p->right) {
q.push(p->right);
}
}
result.push_back(level); //添加每层数据
}
return result;
}
};

将有序数组转换为二叉搜索树

平衡二叉树的根节点的值为数组中的中间值,即中序遍历时,根结点位于正中间;所以使用二分法,先把有序数组的最中间值设为根结点,然后根结点的左孩子是左半段数组的最中间值,根结点的右孩子是右半段数组的最中间值。依次这样,即可以建立一个平衡二叉搜索树。

/**
* 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* sortedArrayToBST(vector<int>& nums) {
return sortedArrayToBST(nums,0,nums.size()-1);
} TreeNode* sortedArrayToBST(vector<int> &nums,int begin ,int end){
if(begin>end)
return NULL;
int mid=(begin+end)/2;
TreeNode* root=new TreeNode(nums[mid]); //根结点,为当前数组的中间值
root->left = sortedArrayToBST(nums , begin , mid - 1);//根结点的左孩子为左半段数组的中间值
root->right = sortedArrayToBST(nums , mid + 1 , end);//根结点的右孩子为右半段数组的中间值
return root;
}
};

LeetCode初级算法(树篇)的更多相关文章

  1. LeetCode初级算法--树01:二叉树的最大深度

    LeetCode初级算法--树01:二叉树的最大深度 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.n ...

  2. LeetCode初级算法--树02:验证二叉搜索树

    LeetCode初级算法--树02:验证二叉搜索树 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...

  3. LeetCode初级算法(其他篇)

    目录 缺失数字 位1的个数 颠倒二进制位 有效的括号 汉明距离 帕斯卡三角形 缺失数字 最初的想法是将0到n全部加起来,再减去输入的数字之和,那么差如果非零的话就是我们所需要的数字.但是一想,可能会发 ...

  4. Leetcode初级算法(链表篇)

    删除链表的倒数第N个节点 感觉自己对于链表的知识还是了解的不够深入,所以没有想到用双指针进行操作.我的想法是这样的,首先计算整个链表的长度,然后遍历到长度减去n的节点处,执行删除操作. 自己的代码: ...

  5. Leetcode初级算法(字符串篇)

    目录 反转字符串 颠倒整数 字符串中的第一个唯一字符 有效的字母异位词 验证回文字符串 实现strStr() 数数并说 最长公共前缀 字符串转整数(atoi) 反转字符串 和vector同样的进行sw ...

  6. LeetCode初级算法(数组)解答

    这里记录了LeetCode初级算法中数组的一些题目: 加一 本来想先转成整数,加1后再转回去:耽美想到测试的例子考虑到了这个方法的笨重,所以int类型超了最大范围65536,导致程序出错. class ...

  7. 【LeetCode算法】LeetCode初级算法——字符串

      在LeetCode初级算法的字符串专题中,共给出了九道题目,分别为:反转字符串,整数反转,字符串中的第一个唯一字符,有效的字母异位词,验证回文字符串,字符串转换整数,实现strStr(),报数,最 ...

  8. LeetCode初级算法之数组:48 旋转图像

    旋转图像 题目地址:https://leetcode-cn.com/problems/rotate-image/ 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: ...

  9. LeetCode初级算法的Python实现--排序和搜索、设计问题、数学及其他

    LeetCode初级算法的Python实现--排序和搜索.设计问题.数学及其他 1.排序和搜索 class Solution(object): # 合并两个有序数组 def merge(self, n ...

随机推荐

  1. do-while-zero 结构在宏定义中的应用

    do while 语句在使用宏定义时是一个有用的技巧,说明如下: 假设有这样一个宏定义 #define macro(condition) / if(condition) dosomething() 现 ...

  2. ffmpeg第三方库编译记录

    最近在研究ffmpeg的编译,之前使用的Ubuntu,需要安装虚拟机,非常麻烦,所以后来改研究在Windows平台编译. 一开始遇到很多挫折,参考了网上很多的帖子,但要么不全要么内容已过期,经过我的反 ...

  3. JSONP -- 跨域数据交互协议

    一.概念 ①传统Ajax:交互的数据格式——自定义字符串或XML描述: 跨域——通过服务器端代理解决. ②如今最优方案:使用JSON格式来传输数据,使用JSONP来跨域. ③JSON:一种数据交换格式 ...

  4. 洛谷【P1104】生日(冒泡排序版)

    题目传送门:https://www.luogu.org/problemnew/show/P1104 题目很简单,我主要是来讲冒泡排序的. 所谓冒泡排序,流程如下: 每次确定一个\(rk\)(从\(n\ ...

  5. ssh免密码登录配置方法,(图示加命令)

    首先,说明一下我们要做的是,serverA 服务器的 usera 用户免密码登录 serverB 服务器的 userb用户. 我们先使用usera 登录 serverA 服务器 [root@serve ...

  6. RESTEasy常用注解

    一.@Path,标注资源类或方法的相对路径          Path参数的形式有三种:          1.固定值          2.纯正则表达式          3.固定值和正则表达式的混 ...

  7. js插件库+bootstrap

    1.Chart.js 官网地址:http://chartjs.cn/ 2.优秀的bootstrap模板推荐 官网地址:http://bootswatch.com 3.wow+animate+js插件库 ...

  8. [poj1273]Drainage Ditches(最大流)

    解题关键:最大流裸题 #include<cstdio> #include<cstring> #include<algorithm> #include<cstd ...

  9. spring----IOC注解方式以及AOP

    技术分析之Spring框架的IOC功能之注解的方式 Spring框架的IOC之注解方式的快速入门 1. 步骤一:导入注解开发所有需要的jar包 * 引入IOC容器必须的6个jar包 * 多引入一个:S ...

  10. sell01 环境搭建、编写持久层并进行测试

    1 环境配置 JDK 1.8 MAVEN 3.5 MYSQL 5.7 VirtualBox 5.1 2 搭建MYSQL环境 下载 VM 和 虚拟镜像文件 虚拟镜像文件:点击前往 技巧01:安装完vir ...