Arts 第十六周(7/1 ~ 7/7)

ARTS是什么?
Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章。


Algorithm

这次说说这周 LeetCode Contest 中两道比较有价值的题目:

LeetCode 1106. Parsing A Boolean Expression

LeetCode 1104. Path In Zigzag Labelled Binary Tree

思路分析(题目一)
给定一个字符串逻辑表达式,里面用字符 t 表示 true,f 表示 false,另外有三种逻辑符号 &、|、!,分别表示与或非,问最后表达式输出的结果,刚看到题目的时候我觉得这道题特别简单,用栈应该很好解决,但是写着写着问题就来了,发现要保存的东西不仅仅是 boolean 字符,还有逻辑符号,不然的话会造成信息缺失。于是我就想到了用两个栈来保存信息,一个栈存逻辑符号,另外一个栈存 boolean 字符,当我们遇到字符 ')' 的时候就向前计算计算到非 boolean 字符为止


参考代码(题目一)

public boolean parseBoolExpr(String expression) {
    Stack<Character> operation = new Stack<>();
    Stack<Character> tf = new Stack<>();
    
    char[] exprArr = expression.toCharArray();
    
    int index = 0;
    
    while (index < exprArr.length) {
        if (exprArr[index] == '!' || exprArr[index] == '|' || exprArr[index] == '&') {
            operation.push(exprArr[index]);
            tf.push(exprArr[index]);
        }
        
        if (exprArr[index] == 't' || exprArr[index] == 'f') {
            tf.push(exprArr[index]);
        }
        
        if (exprArr[index] == ')') {
            boolean cur = tf.pop() == 't' ? true : false;
            char oper = operation.pop();
            while (tf.peek() != oper) {
                if (oper == '|') {
                    cur |= tf.pop() == 't' ? true : false;
                } else if (oper == '&') {
                    cur &= tf.pop() == 't' ? true : false;
                }
            }
            
            if (tf.pop() == '!') {
                cur = !cur;
            }
            
            char res = cur ? 't' : 'f';
            tf.push(res);
        }
        
        index++;
    }
    
    return tf.peek() == 't' ? true : false;
}
复制代码

思路分析(题目二)
这道题纠结了很久,看似二叉树问题,其实本身并没有考传统的二叉树递归遍历之类的东西,而是考的偏数学方面的知识。一般的满二叉树,如果对节点从上到下,从左到右编号,从编号上看,你会发现左节点和父节点的关系是左节点的编号乘上 2 就是父节点的编号,右节点编号减一乘上 2 就是父节点的编号,那反过来说子节点的编号除以 2 都会是父节点的编号(利用程序中的整除性质),如果这道题不反转,就会很简单,直接一个递归或者循环就出来了,但是反转之后,一时半会很难发现规律,这里我们其实可以通过每一行的最大值和最小值来判断,每一行中的节点的理想父节点(在顺序编号下)在上一行中都是位于对称位置,这样我们就可以通过当前节点距中心节点的距离来获知当前行,当前节点的对称节点,然后对称节点除以 2 就是我们当前节点的父节点,以此类推,一个循环就出来了,代码实现一点也不复杂,但是规律难找


参考代码(题目二)

public List<Integer> pathInZigZagTree(int label) {
    List<Integer> result = new ArrayList<>();
    
    int curNode = label;
    
    int curRowMax = 1;
    while (curRowMax < curNode) {
        curRowMax = curRowMax * 2 + 1;
    }
    
    int curRowMin = curRowMax / 2 + 1;
    
    while (curNode > 0) {
        result.add(curNode);
        curNode = (curRowMax - curNode + curRowMin) / 2;
        curRowMax = curRowMin - 1;
        curRowMin = curRowMax / 2 + 1;
    }
    
    Collections.reverse(result);
    
    return result;
}
复制代码

Review

这周没有特别读英文文章,主要时间都花在反复读 Professional: JavaScript for Web Developers 的第三版原版第六章

Professional: JavaScript for Web Developers

感悟和总结都写在了这一期和前一期的 ARTS 的 Share 部分,这里就不做赘述。


Tip

这周在调试前端的时候发现一个问题,就是 CROS 跨域访问的问题,具体没太了解,但是发现了一篇讲述这种问题解决方案的文章 ajax跨域,这应该是最全的解决方案了,按照文章中的指示,我在后台 NodeJS 中 app.js 中添加了如下代码:

app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "*");
    res.header("Access-Control-Allow-Methods", "*");
    res.header("X-Powered-By", ' *')
    //这段仅仅为了方便返回json而已
    res.header("Content-Type", "application/json;charset=utf-8");
    if(req.method == 'OPTIONS') {
        //让options请求快速返回
        res.sendStatus(200); 
    } else { 
        next(); 
    }
});
复制代码

全部打星号,感觉虽然解决了问题,但是还有点暴力,以后再做优化吧,至少清楚了解决类似问题的方法,自己还是需要去了解 CROS 的具体原因,以及浏览器为什么要这么设计,这件事已提到日程上了。


Share

JavaScript 中的对象,这周讲讲继承和多态的实现

JavaScript 中的对象(二)- 继承与多态

转载于:https://juejin.im/post/5d1ffebc6fb9a07ef4442734

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值