leetCode之回溯法

2020-09-24  本文已影响0人  Benzic

首页目录 点击查看

第一题

解题思路

我的答案

var letterCombinations = function (digits) {
    if (!digits.length) return []
    let list = {
        "2": "abc",
        "3": "def",
        "4": "ghi",
        "5": "jkl",
        "6": "mno",
        "7": "pqrs",
        "8": "tuv",
        "9": "wxyz"
    }
    let array = [];
    function generate(curStr, i) {
        if (curStr.length === digits.length) {
            array.push(curStr)
            return
        }
        let letters = list[digits[i]];
        if (letters) {
            for (let key of letters) {

                generate(curStr + key, i + 1)
            }
        }

    }
    generate("", 0)
    return array
};

第二题

输入:n = 3
输出:[
       "((()))",
       "(()())",
       "(())()",
       "()(())",
       "()()()"
     ]

解题思路

我的答案

var generateParenthesis = function (n) {
    let array = [];
    let str = "";

    function generate(str, left, right) {
        if (str.length === 2 * n) {
            array.push(str)
            return
        }
        if (left > 0) {
            generate(str + "(", left - 1, right)
        }
        if (right > left) {
            generate(str + ")", left, right - 1)
        }
    }
    generate(str, n, n)
    return array
};
image.png

第三题

示例

image.png
答案被标成红色。
- 给定的数独序列只包含数字 1-9 和字符 '.' 。
- 你可以假设给定的数独只有唯一解。
- 给定数独永远是 9x9 形式的。

解题思路

我的答案

/**
 * @param {character[][]} board
 * @return {void} Do not return anything, modify board in-place instead.
 */
var solveSudoku = function (board) {
    const rows = new Array(9);
    const cols = new Array(9);
    const blocks = new Array(9);
    const options = ['1', '2', '3', '4', '5', '6', '7', '8', '9'];
    for (let i = 0; i < 9; i++) {
        rows[i] = new Set(options)
        cols[i] = new Set(options)
        blocks[i] = new Set(options)
    }
    function getBlocksIndex(i, j) {
        return (i / 3 | 0) * 3 + j / 3 | 0        //获取当前处于哪个小方块
    }
    for (let i = 0; i < 9; i++) {
        for (let j = 0; j < 9; j++) {
            if (board[i][j] !== '.') {
                rows[i].delete(board[i][j]);
                cols[j].delete(board[i][j]);
                blocks[getBlocksIndex(i, j)].delete(board[i][j])
            }
        }
    }

    function fill(i, j) {
        if (j === 9) {
            i++
            j = 0
            if (i === 9) {
                return true
            }
        }
        if (board[i][j] !== '.') {
            return fill(i, j + 1)
        }
        const blockIndex = getBlocksIndex(i, j);
        for (let num = 0; num < 9; num++) {
            const option = options[num];
            if (!rows[i].has(option) || !cols[j].has(option) || !blocks[blockIndex].has(option)) {
                continue
            }
            board[i][j] = option;
            rows[i].delete(option)
            cols[j].delete(option)
            blocks[blockIndex].delete(option)
            
            if (fill(i, j + 1)) {
                return true
            }
            board[i][j] = ".";
            rows[i].add(option)
            cols[j].add(option)
            blocks[blockIndex].add(option)
        }
        return false
    }

    fill(0, 0)
    return board
};
image.png

第四题

示例

输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
  [7],
  [2,2,3]
]
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

解题思路

我的答案

var combinationSum = function (candidates, target) {
    let arr = [];
    function dfs(value, array) {
        if (value === 0) return arr.push(array.slice());
        if (value < 0) return;
        for (let i = 0; i <= candidates.length - 1; i++) {
            if (!array.length || (array[array.length - 1] >= candidates[i])) {
                let temp = value - candidates[i];
                array.push(candidates[i]);
                dfs(temp, array);
                array.pop()
            }
        }
    }
    dfs(target, [])
    return arr
};
image.png

第五题

示例

输入: n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

解题思路

我的答案

        var combine = function (n, k) {
            let arr = [];

            function dfs(array) {
                if (array.length === k) return arr.push(array.slice());
                for (let i = 1; i <= n; i++) {
                    if (!array.length || array[array.length - 1] > i) {
                        array.push(i);
                        dfs(array);
                        array.pop()
                    }
                }
            }
            dfs([]);
            return arr
        };
image.png

大神答案

自己写出来答案后,看了一下结果实在是有点慢,所以去看了题解,看了一下别人的答案,还是很有借鉴的地方,因为我在for循环这里,每次都需要从1开始,其实很浪费,像下面的方法就优化了for循环,得以提升速度。

var combine = function (n, k) {
    let arr = [];
    function dfs(start, array) {
        if (array.length === k) return arr.push(array.slice());
        for (let i = start; i <= n; i++) {
            array.push(i);
            dfs(i + 1, array);
            array.pop()
        }
    }
    dfs(1, []);
    return arr
};
image.png

第六题

示例

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
  [1,2,2],
  [5]
]

解题思路

我的答案

        var combinationSum2 = function (candidates, target) {
            candidates = candidates.sort((a, b) => {
                return a - b
            })
            let arr = [];
            let obj = {}

            function dfs(target, index, array) {
                if (target === 0 && !obj[array.toString()]) {
                    obj[array.toString()] = true
                    return arr.push(array.slice())
                };
                if (target < 0) return;
                for (let i = index; i <= candidates.length - 1; i++) {
                    let temp = target - candidates[i];
                    array.push(candidates[i]);
                    dfs(temp, i + 1, array);
                    array.pop();
                }
            }
            dfs(target, 0, [])
            return arr
        };
image.png
        var combinationSum2 = function (candidates, target) {
            candidates = candidates.sort((a, b) => {
                return a - b
            })
            let arr = [];

            function dfs(target, index, array) {
                if (target === 0) {
                    return arr.push(array.slice())
                };
                if (target < 0) return;
                for (let i = index; i <= candidates.length - 1; i++) {
                    if (candidates[i - 1] == candidates[i] && i - 1 >= index) continue;
                    let temp = target - candidates[i];
                    array.push(candidates[i]);
                    dfs(temp, i + 1, array);
                    array.pop();
                }
            }
            dfs(target, 0, [])
            return arr
        };
image.png

以上两者明显是第二种更好,空间复杂度也相对较低

第七题

示例

输入: [1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

解题思路

我的答案

var permute = function (nums) {
    let arr = [];
    let obj = {}
    function dfs(array) {
        if (array.length === nums.length) return arr.push(array.slice());
        if (array.length > nums.length) return;
        for (let i = 0; i <= nums.length - 1; i++) {
            if (!obj[i]) {
                obj[i] = true
                array.push(nums[i]);
                dfs(array);
                obj[i] = false
                array.pop()
            }
        }
    }
    dfs([])
    return arr
};
image.png

第八题

示例

输入: [1,1,2]
输出:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

解题思路

我的答案

var permuteUnique = function (nums) {
    let arr = new Set();
    let obj = {}
    nums.sort((a, b) => a - b); // 升序排序
    function dfs(array, index) {
        if (array.length === nums.length) return arr.add(array.slice())
        if (array.length > nums.length) return
        for (let i = 0; i <= nums.length - 1; i++) {
            if (nums[i - 1] === nums[i] && i - 1 >= 0 && !obj[i - 1]) { // 避免产生重复的排列
                continue;
            }
            if (obj[i]) {      // 这个数使用过了,跳过。
                continue;
            }
            array.push(nums[i]);
            obj[i] = true
            dfs(array, i + 1);
            array.pop()
            obj[i] = false
        }
    }
    dfs([], 0)
    return [...arr]
};
image.png

第九题

示例

输入: [1,2,2]
输出:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

解题思路

我的答案

var subsetsWithDup = function (nums) {
    let arr = [];
    nums.sort((a, b) => {
        return a - b
    });

    function dfs(index, array) {
        arr.push(array.slice());
        for (let i = index; i <= nums.length - 1; i++) {
            if (nums[i - 1] === nums[i] && i - 1 >= index) continue;
            array.push(nums[i]);
            dfs(i + 1, array);
            array.pop()
        }
    }
    dfs(0, [])
    return arr
};
image.png

第十题

示例

输入:"AAB"
输出:8
解释:可能的序列为 "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA"。

输入:"AAABBC"
输出:188

解题思路

我的答案

        var numTilePossibilities = function (tiles) {
            let obj = {}
            let arr = new Set()

            function dfs(path) {
                if (path.length) {
                    arr.add(path)
                }
                for (let i = 0; i <= tiles.length - 1; i++) {
                    if (!obj[i]) {
                        obj[i] = true
                        path += tiles[i]
                        dfs(path);
                        obj[i] = false
                        path = path.slice(0, path.length - 1)
                    }
                }
            }
            dfs("")
            return arr.size
        };
image.png
        var numTilePossibilities = function (tiles) {
            let sum = 0;

            function cal(list, n) {
                let ns = Array.from(new Set(Array.from(list)));
                sum += ns.length;
                for (let i = 0, l = ns.length; i < l; i++) {
                    if (n > 1) { 
                        cal(list.replace(ns[i], ''), n - 1);
                    }
                }
            }
            cal(tiles, tiles.length);
            return sum;
        };
image.png

第十一题

示例

输出:low = 100, high = 300
输出:[123,234]

输出:low = 1000, high = 13000
输出:[1234,2345,3456,4567,5678,6789,12345]

解题思路

大神的答案

var sequentialDigits = function(low, high) {
    let ans = [];
    for (i = 1; i <= 9; i++) {
        backtrack(low, high, i, i);
    }
    ans.sort((a, b) => a-b)
    return ans;
    function backtrack (low, high, curNum, curTail) {
        if(curNum >= low && curNum <= high) {
            ans.push(curNum)
        }
        if(curNum > high) {
            return;
        }
        if(curTail + 1 <= 9) {
            backtrack(low, high, curNum*10 + curTail + 1, curTail + 1);
        }
    }
};

image.png
上一篇下一篇

猜你喜欢

热点阅读