前端就该用 JS 刷算法20

125 阅读3分钟

每日一题 -- 树

1026. 节点与其祖先之间的最大差值

1026. 节点与其祖先之间的最大差值

// https://leetcode-cn.com/problems/maximum-difference-between-node-and-ancestor/
// 1026. 节点与其祖先之间的最大差值

/**
 * @分析
 * 1. 自顶向下遍历,带最大最小值的扩展参数,遍历结束之后,返回差值即可
 */
var maxAncestorDiff = function(root) {
    if(!root) return 0
    let res = -Infinity
    const dfs = (root,min,max) => {
        min = Math.min(root.val,min)
        max = Math.max(root.val,max)
        if(!root.left && !root.right){
            res = Math.max(res,max-min)
            return
        }
        if(root.left) dfs(root.left,min,max)
        if(root.right) dfs(root.right,min,max)
    }
    dfs(root,Infinity,-Infinity)
    return res
};

91算法 -- 搜索

301. 删除无效的括号

301. 删除无效的括号

分析

  1. 先把所有执行情况都弄出来,然后写边界,最后进行优化
  2. 首先遍历 s 的每一个字符需要判定的执行的情况有4种
    1. 左括号 -- 存储 或者 删除
    2. 右括号且左括号存储数存在 -- 抵消 或者 删除
    3. 右括号且左括号存储数为0 -- 删除
    4. 其他字符 -- 跳过
  3. 边界
    1. 保存一个全局最小的删除数 deleteCount,当 del 的值大于 deleteCount 的时候,返回;注意,由于需要设置真正的初始最小值,所以在遇到右括号的时候,先进行抵消操作,这样首次满足条件返回字符串的时候, del 其实就是最小的删除数,后续的值都以它为标准即可
    2. 当遍历 s 结束的时候,如果 leftCount 也清空了,则这条路径是好的;但是需要注意的是,很有可能存在不同路径得到相同的字符串的情况,所以还需要数组去重

回调函数的参数

  1. subStr -- 遍历过程中保存的字符串
  2. leftCount -- 左括号存储数
  3. index -- 遍历的下标,作为 s 遍历结束的终止条件和查找 s 字符
  4. del -- 表示当前路径已经删除了字符的值
// https://leetcode-cn.com/problems/remove-invalid-parentheses/
// 301. 删除无效的括号

/**
 * @分析
 * 1. 维护一个保存左括号的栈,当遇到右括号的时候,如果栈为空,当次路径无效
 * 2. 如果栈不为空,则有个选择,出栈抵消,或者删除当前的右括号
 * 3. 最后走完 s,要保证栈为空,且删除的值要最小
 */
var removeInvalidParentheses = function (s) {
    const res =[]
    // 删除次数,默认是最大值,然后第一次取值后替换成删除次数最小的值
    //  因为默认是抵消的,所以第一个达到要求的肯定是删除次数最小的那个
    let deleteCount = Infinity;
    const recursion = (subStr, leftCount, index, del) => {
        // 边界条件1:如果删除次数大于最小删除,则不符合,返回
        if (del > deleteCount) return
        // 边界条件2:已经遍历完
        if(s.length === index){
            if(leftCount === 0 && res.indexOf(subStr) === -1){
                // 符合条件
                res.push(subStr)
                deleteCount = Math.min(del,deleteCount)
                return 
            }else{
                return
            }
        }
        // 正常情况下
        if (s[index] === '(') {
            recursion(subStr + s[index], leftCount + 1, index + 1, del)
            // 还有删除重造的可能
            recursion(subStr, leftCount, index + 1, del + 1)
        }
        if (s[index] === ')' && leftCount) {
            // 默认先抵消
            recursion(subStr + s[index], leftCount - 1, index + 1, del)
            // 走另外一条路,删除这个字符
            recursion(subStr, leftCount, index + 1, del + 1)
        } 
        if(s[index] === ')' && leftCount === 0){
            recursion(subStr, leftCount, index + 1, del + 1)
        } 
        if(s[index]!=='(' && s[index]!==')') {
            recursion(subStr + s[index], leftCount, index + 1, del)
        }
    }
    recursion('',0,0,0)
    return res
};