今天看了下LeetCode上的题目,一千多道,以这种一天三道题的速度,一年都解不完,另外现在的是简单难度,以后困难难度指不定三天都做不完一道。。啧啧,越想越激动呢~~接下来两年的学习目标都有了哈!闲话少叙,刷题继续。
平衡二叉树
题目:给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
思路:我觉得这个题啊,做着做着就重复了,反正性能怎么样不好说,但是这个平衡的判断,遍历左右高度不就ok了?我先去撸代码,希望别打脸。滚回来了,没打脸,思路可行,就是性能感人。
另外再吐槽一下这个题目,我不知道是中文翻译的问题还是出题人自己都没明白什么叫做平衡二叉树,反正这个问题的题目表达就有问题、我一开始按照题目要求怎么想都有点问题,后来问了人才知道题目表达错了
实际上的平衡二叉树:只要本身左右平衡,并且左树右树平衡就行了。
继续说这个题的代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
if(root==null){
return true;
}
int left = getTreeLen(root.left);
int right = getTreeLen(root.right);
//整体都不平衡了直接返回falsefalse
if(left-right>1 || left-right<-1){
return false;
}
//整体平衡再判断左右子树平不平衡
return isBalanced(root.left) && isBalanced(root.right);
}
public int getTreeLen(TreeNode tree){
return tree==null?0:Math.max(getTreeLen(tree.left),getTreeLen(tree.right))+1;
}
}
在会了求二叉树深度的那个题以后,这个只需要再加工加工就行了。如图。反正性能不咋地但是执行速度还不错。看了题解,这种双递归居然是答案的主流。还有别的方法但是贪多嚼不烂,我就不再写了,感兴趣的自己去看吧,真感觉LeetCode评论贼出人才。
二叉树的最小深度
题目:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明: 叶子节点是指没有子节点的节点。
思路:这接二连三连续不断的二叉树,有点疲惫啊~继续说思路,上一道题求最大深度,这道题就最小深度。大同小异吧,我先去研究研究怎么递归。
好的,撸完代码回来了,只能说提交相当于debug。在一次次错误的修改中完成的。思路就是我刚刚说的思路,然后代码性能我觉得已经很棒了:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if(root==null){
return 0;
}
//左右都没有才是叶子节点
if(root.left==null && root.right==null){
return 1;
}
//如果只是一边没有则不是叶子节点,还是要继续往下遍历
if(root.left==null){
return minDepth(root.right)+1;
}
if(root.right==null){
return minDepth(root.left)+1;
}
return Math.min(minDepth(root.left),minDepth(root.right))+1;
}
}
上面的逻辑其实很清楚,非要说坑也就是如果一个节点只有一边有节点还是要继续遍历,而且不能用比较的那个,因为那样肯定会返回0,所以左边或右边没有要单独挑出来返回。剩下就没了。因为这个题目我自己的答案就性能和执行时间很优,所以就不看解析了。
路径总和
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。说明: 叶子节点是指没有子节点的节点。
思路:莫名开心,这几道题都是自己直接做出来的。所谓的百变不离其中吧。其实这几道二叉树的题只能说千丝万缕的关系并且一窍通窍窍通。不装13了,继续说思路。思路就是判断到每一个叶子结点的和。但凡有一个true则true,不然就是false。每一个到叶子节点的和要用到递归。其实这道题还是我想复杂了。第一遍没对是因为我没考虑负数。以为肯定都是正数呢,还做了很多额外的判断,后来知道有负数了改了一下就通过了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
//直接空树,肯定返回false
if(root==null){
return false;
}
//如果这个节点是叶子节点,一定要等于sum才true
if(root.left==null && root.right==null && root.val==sum){
return true;
}
//如果这个节点是叶子节点,还不等于sum,返回false
if(root.left==null && root.right==null && root.val!=sum){
return false;
}
//如果这个节点还有左右节点,则递归去判断
if(root.left!=null && root.right!=null){
return hasPathSum(root.left,sum-root.val)||hasPathSum(root.right,sum-root.val);
}
//左结点不是空则右节点一定是空,所以只要递归左结点
if(root.left!=null){
//这个参数是sum-root.val。因为把到当前节点的和减去
return hasPathSum(root.left,sum-root.val);
}
//同上,不多说了
if(root.right!=null){
return hasPathSum(root.right,sum-root.val);
}
//其实这步是不会走到的。所以不管是true还是false无所谓,为了语法过得去怎么也得写一个
return false;
}
}
然后我觉得这个思路很明了,就是性能差了点。接下来去看看大神的思路吧:
回来了,有点头疼。我上面的代码,我知道很麻烦,但是我是故意这么写的!!!为了性能!!我以为我判断左节点右节点空不空,然后递归的时候不用递归是节省性能的,结果看了别人说的才发现不判断这个不管不顾直接双递归才是性能最好的??WHY?
反正只要在我上面的判断中最后两个去掉,然后第三个判断的&&改成||就ok了,执行时间就上来了,性能就下去了,反正情况就这样了。
反正给我的教训就是以后再也不特意为了性能写代码了。
本文章就到这,如果稍微帮到你了记得点个喜欢点个关注,祝大家工作顺顺利利!