日常刷题0x12之德玛蹲草丛

157 阅读1分钟

此阶段给自己定的目标是:做过的这些题每天坚持继续刷二遍,每道题做过之后开始尝试多解法尝试解题。上一阶段是感知都有什么题目,此阶段主要系统化常规题解套路知识,牢记牢记此阶段目的。

题号:46
//回溯,每一次决策就把决策选择的元素放入路径中,完了就把该结果从路径中移除
var permute = function (nums) {

    let result = [], path = []
    let set = new Set(nums)
    let backtrack = (curSet) => {
        if (curSet.size == 0) {
            result.push(path.slice(0))
        }
        for (let item of curSet) {
            path.push(item)
            //每一次为了保持一个纯净的遍历集合都开辟一个新的浪费空间
            let nextSet = new Set(curSet)
            nextSet.delete(item)
            backtrack(nextSet)
            path.pop()
        }
    }
    backtrack(set)
    return result
};

var permute = function (nums) {

    let result = [], path = []
    let backtrack = () => {
        if (path.length == nums.length) {
            result.push(path.slice(0))
        }
        for (let item of nums) {
            //结合题意设置一些变量,状态位等使得减少局部变量的开辟导致的空间浪费
            if (path.includes(item)) {
                continue
            }
            path.push(item)
            backtrack()
            path.pop()
        }
    }
    backtrack()
    return result
};
题号:47
var permuteUnique = function (nums) {

    nums.sort((a, b) => {
        return a - b
    })

    //used记录路径上已经使用过的节点
    let result = [], path = [], used = new Array(nums.length).fill(0)

    let backtrack = () => {
        if (path.length == nums.length) {
            result.push(path.slice(0))
            return
        }
        //map记录当前已经决策过的可能选择,剪枝掉不需要再做选择
        let map = new Map()
        for (let i = 0; i < nums.length; i++) {
            if (used[i] == 1) {
                continue
            } else {
                let num = nums[i]
                if (map.has(num)) {
                    continue
                } else {
                    map.set(num, 1)
                    used[i] = 1

                    path.push(num)
                    backtrack()
                    path.pop()
                    used[i] = 0
                }
            }
        }

    }
    backtrack()
    return result
};
题号:77
var combine = function (n, k) {

    let result = [], path = []
    let backtrack = (begin) => {

        if (path.length == k) {
            result.push(path.slice(0))
            return
        }
        for (let i = begin; i < n; i++) {
            let num = i + 1
            path.push(num)
            backtrack(i + 1)
            path.pop()
        }
    }
    backtrack(0)
    return result
};
题号:39
var combinationSum = function (candidates, target) {

    candidates.sort((a, b) => {
        return a - b
    })
    let result = [], path = []
    let dfs = (begin, num) => {
        if (num < 0) {
            //已经不符合题意了
            return
        }
        if (num == 0) {
            //记录一个结果
            result.push(path.slice(0))
        }
        //从数组中挑出元素满足题意,元素可重复使用(组合问题不讲究顺序)
        //之前用过的就不能再用放在组合中就是一种情况
        for (let i = begin; i < candidates.length; i++) {
            path.push(candidates[i])
            dfs(i, num - candidates[i])
            path.pop()
        }
    }
    dfs(0, target)
    return result
};
题号:40

var combinationSum2 = function (candidates, target) {

    candidates.sort((a, b) => {
        return a - b
    })
    let result = [], path = []
    let dfs = (begin, num) => {
        if (num < 0) {
            return
        }
        if (num == 0) {
            result.push(path.slice(0))
            return
        }
        //candidates可能有重复元素那么需要记录横向选择不重复的元素
        let map = new Map()
        for (let i = begin; i < candidates.length; i++) {
            let item = candidates[i]
            if (map.has(item)) {
                continue
            } else {
                map.set(item, 1)
                path.push(item)
                dfs(i + 1, num - item)
                path.pop()
            }
        }
    }
    dfs(0, target)
    return result
};