
本文介绍一种递归算法,用于将具有层级依赖关系的嵌套数组(如树形分支结构)展开为所有合法路径组合的扁平字符串数组,适用于生成笛卡尔式路径、配置组合或枚举多级选项等场景。
本文介绍一种递归算法,用于将具有层级依赖关系的嵌套数组(如树形分支结构)展开为所有合法路径组合的扁平字符串数组,适用于生成笛卡尔式路径、配置组合或枚举多级选项等场景。
该问题本质是带层级约束的路径展开:每一层子数组并非与上一层所有元素自由组合(即非简单笛卡尔积),而是严格按顺序“一对一”分配——第 i 层的第 k 个子数组,只作用于第 i−1 层第 k 个已生成的前缀。这种结构天然对应一棵分支数可变的树,其中每个节点的子节点数量由其所在位置决定。
以下是一个健壮、可读性强的 JavaScript 实现:
function distributeTreeBranches(data) {
const combine = (index = 0, offsets = [0]) => {
// 确保下一层偏移量存在(惰性初始化)
if (offsets.length = data.length) {
return [''];
}
// 获取当前层待处理的项:
// - 若 index === 0,直接取 data[0](顶层字符串数组)
// - 否则取 data[index][offsets[index]](对应前缀位置的子数组)
const currentItems = index === 0
? data[0]
: data[index][offsets[index]];
// 对当前层每个 item,递归生成后续路径,并拼接
return currentItems.flatMap(item => {
const suffixes = combine(index + 1, offsets);
const results = suffixes.map(suffix => item + suffix);
// 关键:为下一个前缀推进下一层偏移量
offsets[index + 1]++;
return results;
});
};
return combine();
}
// 测试用例
const input = [
["a", "b"],
[["c", "d"], ["e", "f", "g"]],
[["h", "i"], ["j"], ["k", "l"], ["m"], ["n", "o", "p"]]
];
console.log(distributeTreeBranches(input));
// 输出: ["ach","aci","adj","bek","bel","bfm","bgn","bgo","bgp"]
✅ 核心设计要点说明:
- offsets 数组:记录每层当前正在服务的“前缀索引”,实现父子节点间的精确绑定;
- flatMap + map 组合:既完成递归展开,又自然聚合结果;
- index === 0 特判:顶层无父级,直接展开;
- 终止条件返回 ['']:保证字符串拼接时 item + '' 不改变原始值,逻辑统一。
⚠️ 注意事项:
- 输入结构必须满足:data[0] 是字符串数组;对 i > 0,data[i] 是数组的数组,且 data[i].length 至少等于上一层生成的前缀数量(否则会越界);
- 该算法时间复杂度为 O(N)(N 为最终结果总字符数),空间复杂度取决于最大递归深度与中间状态,对深层嵌套仍保持稳定;
- 若需支持非字符串类型(如对象、数字),可将拼接逻辑 item + suffix 替换为自定义合并函数(如 merge(item, suffix))。
此方法清晰分离了层级调度与内容组合,避免了传统双重循环易错的索引管理,是处理此类“分支对齐型”组合问题的推荐范式。











