题目
给定一个字符串,求所有子串,包括空字符串
- 假设给定的字符串是abc,那么以a开头的有abc、ab、ac,以b开头的有bc、b,以c开头的有c,然后是空字符串
- 具体表现如下图所示
- 也就是意味着每到一个字符,都有要和不要两种情况
- 当从a开始时,需要创建要a和不要a的路径
- 在上面基础上到b时,需要创建有b和无b的路径
- 在上面基础上到c时,需要创建有c和无c的路径
- 所以递归结构需要两条路,一条有当前字符往下递归,一条无当前字符往下递归
function getString(str) {
let strArr = str.split("");
// collectArr记录之前路径
function getSub(strArr, i, collectArr) {
if (i === strArr.length) {
console.log(collectArr.join(""));
return;
}
// 有当前字符
let hasCollect = [...collectArr];
// 没有当前字符
let noCollect = [...collectArr];
hasCollect[i] = strArr[i];
getSub(strArr, i + 1, hasCollect);
getSub(strArr, i + 1, noCollect);
}
getSub(strArr, 0, []);
}
getString("abc");
function getAllSubstrings(str) {
const substrings = new Set(); // 使用 Set 避免重复
function backtrack(index, current) {
if (index === str.length) {
substrings.add(current);
return;
}
// 选择当前字符
backtrack(index + 1, current + str[index]);
// 不选择当前字符
backtrack(index + 1, current);
}
backtrack(0, "");
return Array.from(substrings);
} // 示例 console.log(getAllSubstrings("abc")); // 输出: ["", "a", "b", "c", "ab", "ac", "bc", "abc"]
- 另一种省空间的做法,通过递归回溯性改变|还原值
function getString(str) {
let strArr = str.split("");
// collectArr记录之前路径
function getSub(strArr, i) {
if (i === strArr.length) {
console.log(strArr);
return;
}
let preRes=strArr[i+1];
getSub(strArr, i + 1);
strArr[i+1]="";
getSub(strArr, i + 1);
strArr[i+1]=preRes;
}
getSub(strArr, 0, []);
}
getString("abc");