前端就该用 JS 刷算法21

168 阅读2分钟

每日一题 -- 树

865.具有所有最深节点的最小子树

865.具有所有最深节点的最小子树

// https://leetcode-cn.com/problems/smallest-subtree-with-all-the-deepest-nodes/
// 865.具有所有最深节点的最小子树

/**
 * @分析
 * 1. 比较的是深度,所以自顶向下求深度的时候就需要带上深度扩展参数
 * 2. 为了左右子树都能直接判断到,所以不设置 dfs 下去的判断,而是直接进行节点判空
 */
var subtreeWithAllDeepest = function (root) {
    const dfs = (root, depth) => {
        if (!root) return [root, depth]
        const [ln, ld] = dfs(root.left, depth + 1)
        const [rn, rd] = dfs(root.right, depth + 1)
        // 进行判断
        if (ld === rd) return [root, ld]
        if (ld < rd) return [rn, rd]
        if (ld > rd) return [ln,ld]
    }
    return dfs(root, -1)[0]
};

91算法 -- 背包问题

416. 分割等和子集

416. 分割等和子集

想说的话

  • 这题做了 1h 多了,一开始是按照背包来写的,但是想不出来,然后就想用回溯来做,然后超时了,有太多重复的情况了,最后没做出来,暂时就这样吧,明天抽时间看看题解再搞,下一部分学习咯
// 416. 分割等和子集
// https://leetcode-cn.com/problems/partition-equal-subset-sum/

/**
 * 深度遍历+回溯的方式 --- 超时了
 * @分析 :
 * 1. 先求总和,然后根据奇偶来判断并求出真正需要分割出来的 target 值
 */
var canPartition = function (nums) {
    const rest = nums.reduce((pre, cur) => pre + cur, 0) // 一次遍历
    if (rest % 2) return false // 如果是奇数,则不能平分
    const target = rest >>> 1 //取中间值
    let res = false
    const dfs = (index, total) => {
        if (total > target || index === nums.length) return
        if (total === target) {
            res = true
            return
        }
        dfs(index + 1, total + nums[index])
        dfs(index + 1, total)
    }
    dfs(0, 0)
    return res
};

/**
 * 继续回溯 + 继续超时
 * @分析
 * 1. 分别保存左右两个数组的值,然后当遍历结束进行判断
 */
var canPartition = function (nums) {
    let res = false
    const dfs = (index, left, right) => {
        if (index === nums.length) {
            if (left === right) {
                res = true
                return
            }
            return
        }
        dfs(index + 1, left + nums[index], right) //放左边
        dfs(index + 1, left, right + nums[index]) // 还是放右边
    }
    dfs(0, 0, 0)
    return res
};

/**
 * dp
 * @分析
 * 1. 
 */
var canPartition = function (nums) {
    const rest = nums.reduce((pre, cur) => pre + cur, 0) // 一次遍历
    if (rest % 2) return false // 如果是奇数,则不能平分
    const target = rest >>> 1 //取中间值
    let res = false
    const len = nums.length 
    let dp = new Array(len)
    dp[0] = [0, nums[0]]
    for (let i = 1; i < len; i++) {
        console.log(dp,dp[i-1].map(i=>i),i)
        dp[i] = [...dp[i-1],...dp[i-1].map(item => {
            if (item+nums[i] === target) {
                 res = true;
            } else if (item+nums[i] < target) {
                return item+nums[i]
            }else{
                return item
            }
        })]
    }
    return res
}