5月28日 每日leetcode三题(501/94/65)

前言

刷5月15日的老题。今天刷的是501.中序遍历二叉树找众数、94.二叉树的中序遍历、65.有效数字。

501.中序遍历二叉树找众数(容易):
题目描述:

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

·结点左子树中所含结点的值小于等于当前结点的值
·结点右子树中所含结点的值大于等于当前结点的值
·左子树和右子树都是二叉搜索树

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-mode-in-binary-search-tree

题解:

由于给定的二叉树是BST,中序遍历可以很好地利用它的特性,按升序获得序列。寻找众数,可以即时记录一个结果数组和一个max值,判断当前值和上一个值是否相等。不相等,则将计数器置1,并清空;加入相等,则继续计数。当计数器大于max值,就清空并更新结果数组;假如出现多个众数,则在原有基础上更新结果数组。

Code
var findMode = function(root) {
    let preNode=null;
    let count=1;
    let max=1;
    let res=[];
    const helper=(root)=>{
        if(!root) return;
        helper(root.left);
        if(preNode){
            if(root.val==preNode.val) count++;
            else count=1;
        }
        if(count>max){
            max=count;
            res=[];
            res.push(root.val);
        }else if(count==max){
            res.push(root.val);
        }
        preNode=root;
        helper(root.right);
    }
    helper(root);
    return res;
};
94.二叉树的中序遍历(中等):
题目描述:

给定一个二叉树,返回它的中序遍历。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal

题解:

跟着上一题用了递归,时间复杂度是O(n)。除此之外还可以使用莫里斯遍历(维持树的原有结构)。
榜一的迭代法也比较快,有两个比较好理解的,也放上来。

Code
//递归
var inorderTraversal = function(root) {
    let res=[];
    const helper=(root)=>{
        if(!root) return;
        helper(root.left);
        res.push(root.val);
        helper(root.right);
    }
    helper(root);
    return res;
};
//莫里斯遍历
var inorderTraversal = function(root) {
    let res=[],cur=root;
    let mostRight=null;
    while(cur){
        if(!cur.left){
            res.push(cur.val);
            cur=cur.right;
        }else{
            mostRight=cur.left;
            while(mostRight.right&&mostRight.right!=cur){
                mostRight=mostRight.right;
            }
            if(!mostRight.right){
                mostRight.right=cur;
                cur=cur.left;
            }else{
                res.push(cur.val);
                mostRight.right=null;
                cur=cur.right;
            }
        }
    }
    return res;
};
//40ms,将节点和值都存入栈里进行判断,比较巧妙。
var inorderTraversal = function(root) {
    var s = [root];
    var l = [];

    while(s.length) {
        var n = s.pop();
        if (n && n.val) {
            var {left, right, val} = n;
            if (right) s.push(right);
            s.push(n.val);
            if (left) s.push(left);
        } else if (n) {
            l.push(n);
        }
    }
    return l;
};
//44ms,栈存储所有的根节点,逐层遍历。
var inorderTraversal = function(root) {
    if (!root) return []
    const res = []
    const stack = []
    let curr = root

    while(curr || stack.length) {
        while(curr) {
            stack.push(curr)
            curr = curr.left
        }
        curr = stack.pop()
        res.push(curr.val)
        curr = curr.right
    }

    return res
};
65.有效数字(困难):
题目描述:

验证给定的字符串是否可以解释为十进制数字。
例如:

“0” => true
" 0.1 " => true
“abc” => false
“1 a” => false
“2e10” => true
" -90e3   " => true
" 1e" => false
“e3” => false
" 6e-1" => true
" 99e2.5 " => false
“53.5e93” => true
" --6 " => false
“-+3” => false
“95a54e53” => false

说明: 我们有意将问题陈述地比较模糊。在实现代码之前,你应当事先思考所有可能的情况。这里给出一份可能存在于有效十进制数字中的字符列表:

数字 0-9
指数 - “e”
正/负号 - “+”/"-"
小数点 - “.”
当然,在输入中,这些字符的上下文也很重要。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-number

题解:

这种题真是我的噩梦,常规解法是处理字符串,可以用正则表达式。不过看到有状态机的解法,大呼过瘾(学以致用,大佬太强了)。其实状态机和正则表达式是可以相互转化的,不难理解。另外还有一些奇技淫巧…mark下来。

Code
//巧解
var isNumber = function(s) {
    return !Number.isNaN(s.trim().length ? + s : NaN)
};
//正则表达式
var isNumber = function(s) {
  // 直接先去除两头空格就不用考虑两头有空格的情况了
  s = s.trim();
  // 加上^$确保匹配的是整个字符串而不是字符串中的一部分
  // 1. 和.1都是true,所以要这样判断
  // 后面是e的部分e后面跟的数字可正可负但是必须为整数
  const flag = /^([-+]?(\d+(\.\d*)?|\.\d+)(e[-+]?\d+)?)$/.test(s);
  return flag;
};
//状态机
var isNumber = function(s) {
    let state = 0, 
        finals = [0,0,0,1,0,1,1,0,1],
        transfer = [[ 0, 1, 6, 2,-1,-1],
                    [-1,-1, 6, 2,-1,-1],
                    [-1,-1, 3,-1,-1,-1],
                    [ 8,-1, 3,-1, 4,-1],
                    [-1, 7, 5,-1,-1,-1],
                    [ 8,-1, 5,-1,-1,-1],
                    [ 8,-1, 6, 3, 4,-1],
                    [-1,-1, 5,-1,-1,-1],
                    [ 8,-1,-1,-1,-1,-1]], 
        make = (c) => {
            switch(c) {
                case " ": return 0;
                case "+":
                case "-": return 1;
                case ".": return 3;
                case "e": return 4;
                default:
                    let code = c.charCodeAt();
                    if(code >= 48 && code <= 57) {
                        return 2;
                    } else {
                        return 5;
                    }
            }
        };
    for(let i=0; i < s.length; ++i) {
        state = transfer[state][make(s[i])];
        if (state < 0) return false;
    }
    return finals[state];
};
作者:user8973
链接:https://leetcode-cn.com/problems/valid-number/solution/biao-qu-dong-fa-by-user8973/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值