DFS复习

1.括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的括号组合。

例如,给出 n = 3,生成结果为:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]

思路:
有效括号的条件:每个左括号都有一个右括号与之匹配
(1)通过dfs每次插入一个括号,并记录剩余左右括号的个数
(2)当剩余左括号比剩余右括号多时,必然有左括号在后面插入后无法匹配,直接返回
(3)左右括号个数都使用完时,将字符串存入数组。

var generateParenthesis = function (n) {
    let ans = [];
    const dfs = (left, right, str) => {
        if (left > right) return;/* 左边有无法匹配的 */
        if (!left && !right) {
            ans.push(str);
            return;
        }
        if (left) dfs(left - 1, right, str + '(');
        if (right) dfs(left, right - 1, str + ')');
    }
    dfs(n, n, '');
    return ans;
};

2.N皇后问题

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
n皇后

输入: 4
输出: [
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。

思路:
放置皇后的坐标需要具备的条件:
(1)不能和前面放置的皇后在同一列 y2!=y1
(2)不能和前面放置的皇后在同一对角线,|x2-x1|!=|y2-y1|
dfs按照层数选取放置位置(按照上述两个条件判断所便利的位置是否可以放置),用position存各层放置的坐标,所有皇后已经放置完则将position记录的联系转化到字符串,存入数组即可。

var solveNQueens = function (n) {
    let ans = [];
    var isValid = (x, y, position) => {
        /* 遍历x前面已经放置的层数 */
        for (let prex = 0; prex < x; prex++) {
            if (position[prex] === y)/* y列已经放置过 */
                return false;
            /* 在对角线上 */
            if (Math.abs(x - prex) === Math.abs(y - position[prex]))
                return false;
        }
        return true;
    }
    var getString = position => {
        let res = [];
        for (let i = 0; i < n; i++) {
            res[i] = '';
            for (let j = 0; j < n; j++) {
                res[i] += position[i] === j ? 'Q' : '.';
            }
        }
        return res;
    }
    var dfs = (x, position) => {
        if (x == n) {/* 全部已经放置完 */
            ans.push(getString(position));
            return;
        }
        for (let y = 0; y < n; y++) {
            if (isValid(x, y, position)) {/* 判断(x,y)是否能放 */
                position[x] = y;
                dfs(x + 1, position);
            }
        }
    }
    dfs(0, []);
};

3.复原ip地址

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]

步骤:
(1)dfs每次切割1-3个字符形成串tmp,将切割的字符串存入数组arr
切割字符串符合的条件:
a.一位且转化为数字是0 ->tmp==='0'
b.转化为数字大小在[1,256]范围内不能有前导零->parseInt(tmp) > 0 && parseInt(tmp) < 256
(2)将剩余字符串str.substr(i)和数组arr穿给下一层继续选择切割
(3)存满4层,若此时str为空,说明所有字符都已经按照上述条件存入数组,利用join将数组转化为字符串并在中间加入分隔符.,存到Set中
(4)将Set转化为数组返回

var restoreIpAddresses = function (s) {
    let ans = new Set();
    const dfs = (str, arr, level) => {
        if (level == 4) {
            if (!str)
                ans.add(arr.join('.'));
            return;
        }
        for (let i = 1; i <= Math.min(str.length, 3); i++) {
            let tmp = str.substr(0, i);//切割前i个
            if (tmp === '0' || tmp.charAt(0) != 0 && parseInt(tmp) > 0 && parseInt(tmp) < 256) {
                arr[level] = tmp;
                dfs(str.substr(i), arr, level + 1);/* str切割i个传给下一层 */
            }
        }
    }
    dfs(s, [], 0);
    return [...ans];
};
posted @ 2020-04-20 11:44  aeipyuan  阅读(138)  评论(0编辑  收藏  举报