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 皇后问题的解决方案。
输入: 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];
};