二叉树的最大深度

二叉树,所以可以考虑用递归来做。由于根节点已经算过了,所以需要加上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. loj516dp一般看规律

    STL 这...我只能说是...考得是... STL的正确用法? #include<iostream> #include<cstdio> #include<cstdlib ...

  2. 2017-2018-1 20179215《Linux内核原理与分析》第三周作业

    本次作业分为两部分:第一部分为实验.主要目的是进行基于MYKERNEL的一个简单的时间片轮转多道程序内核代码分析.第二部分为阅读教材,了解LINUX进程调度等. 一.实验部分 实验过程如过程所述:使用 ...

  3. centos 6 rsync+inotify 实时同步

    主机名.ip: server 172.31.82.184 client  172.31.82.185 需求: 1.server端 ”/data/server“ 做为client端 “/data/cli ...

  4. 编写dockerfile

    参考:http://www.cnblogs.com/liuyansheng/p/6098470.html 一.dockerfile介绍: 是一种被Docker程序解释的脚本,Dockerfile由一条 ...

  5. HDOJ2043(JAVAset容器练习)

    import java.io.PrintWriter; import java.util.HashSet; import java.util.Scanner; public class Main { ...

  6. 【转】Pro Android学习笔记(十):了解Intent(上)

    目录(?)[-] Intent基本含义 系统的Intent Android引入了Intent的概念来唤起components,component包括:1.Activity(UI元件) 2.Servic ...

  7. Spring boot 学习二:入门

    1: 需要的环境: JDK:至少JDK7才支持Spring boot maven:至少3.2 spring-boot:1.2.5.RELEASE(在pom.xml中指定) 2: 创建一个maven工程 ...

  8. ML 徒手系列 SVM

    在Lagrange乘子法中,介绍了如何构建及如何使用对偶函数,对目标问题进行求解. 这一章利用L乘子法对SVM进行推导. SVM 即支持向量机,是通过求解超平面进行分类的一种算法.所谓的支持向量,是在 ...

  9. ML 徒手系列 最大似然估计

    1.最大似然估计数学定义: 假设总体分布为f(x,θ),X1,X2...Xn为总体采样得到的样本.其中X1,X2...Xn独立同分布,可求得样本的联合概率密度函数为: 其中θ是需要求得的未知量,xi是 ...

  10. RAC环境下ORACLE序列缓存导致序列混乱

    目前项目中发现了这样一个问题,在数据库部署了RAC环境之后,偶尔会出现从Oracle Sequence所取出来的数是混乱的,比如第二次比第一次所取的数要小.这样当程序的逻辑依赖于ID的大小来排序时,就 ...