二叉树的最大深度

二叉树,所以可以考虑用递归来做。由于根节点已经算过了,所以需要加上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. 本地windows安装memcached服务

    1.安装到系统服务中: 在doc中:执行此软件 memcached.exe -d install(如果提示错误,要找到cmd.exe用管理员身份打开) 安装后在,服务里吗就有个服务了,如果没有启动,点 ...

  2. Qt Quick之Canvas

    QML中的Canvas,俗称画布,它用来定义一个绘图区域,可以使用ECMAScript代码来绘制直线,矩形,贝塞尔曲线,弧线,图片,文字等图元,还可以为这些图元应用填充颜色和边框颜色,甚至还可以进行低 ...

  3. iOS NET Error Code

    see NSURLError.h Define NSURLErrorUnknown = -, NSURLErrorCancelled = -, NSURLErrorBadURL = -, NSURLE ...

  4. 理解Promise

    一.Propmise基本用法 Promise用于发送一个异步完成的结果,是替代回调函数的另一种选择.可以把Promise理解为一种异步函数. 以下函数通过一个Promise来异步地返回一个结果 fun ...

  5. git rebase小计(转)

    git rebase,顾名思义,就是重新定义(re)起点(base)的作用,即重新定义分支的版本库状态.要搞清楚这个东西,要先看看版本库状态切换的两种情况: 我们知道,在某个分支上,我们可以通过git ...

  6. linux下mysql配置查询

    1.查看mysql的数据文件存放位置 show variables; 显示结果中的: datadir的值即是. 2.查看mysql是否支持表分区 SHOW VARIABLES LIKE '%parti ...

  7. 转:删除redis所有KEY

    转自:http://ssuupv.blog.163.com/blog/static/1461567220135610456193/ 批量删除Key Redis 中有删除单个 Key 的指令 DEL,但 ...

  8. 【转】 Pro Android学习笔记(五六):配置变化

    目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...

  9. web攻击之二:CSRF跨站域请求伪造

    CSRF是什么? (Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为“One Click ...

  10. 通过能别的主机连接yum库

    本地有两台主机,分别为:192.168.2.131/24和192.168.2.132/24,本地yum源只能连接互联网: 这两台设备的虚拟机配置如下: 现有一台主机:172.16.254.88/16可 ...