function dfsFn(list, value) {
let res = []
function dfs(arr, ids=[]) {
for (const item of arr) {
if (item.id === value) {
res = [...ids, ...[item.id]]
return
} else {
if (item.children) {
dfs(item.children, ids.concat([item.id]))
}
}
}
}
dfs(list)
return res
}
const value = '112' const fn = (value) => { let vals = value.split(''); //1 11 112 for (let i = 0; i < vals.length; i++) { let v = vals.slice(0,i+1).join('') console.log(v) } } fn(value)
const bfs = data => {
const queue = [...data]
let res = []
while(queue.length) {
let node = queue.shift()
if (node.children) {
for (let child of node.children) {
queue.push(child)
}
res.push(node.id)
}
}
return res
}
var searched = [];
var stack = [];
var has = false;
var id = '24';
function DFS(arr) {
//深度遍历
if (isEnd(arr)) {
if (arr.id == id) {
return true;
} else {
stack.pop();
}
}
for (var i = 0; i < arr.child.length; i++) {
var node = arr.child[i];
if (has) {
break;
}
if (!searched.includes(node.id)) {
searched.push(node.id);
stack.push(node.id);
if (DFS(node)) {
has = true;
return stack;
}
}
}
return stack;
}
function isEnd(arr) {
if (!arr.child || arr.id == id) {
return true;
}
}
// 回溯
function fn(list, value) {
let res = []
function helper(list, node) {
if (node.id === value) {
res = [...list]
return
}
if (!node.children || !node.children.length) {
return
}
for (let item of node.children) {
list.push(item.id)
helper(list, item)
list.pop()
}
}
helper([], {children:list})
return res
}
let result = []; function findParentId(list2, val) { for (let key of list2) { console.log(key) if (key.id === val) { result.push(key.id); return result; } if (key.children) { result.push(key.id); let re = findParentId(key.children, val); if (re && re.length) { return re; } else { result.pop(); }`
class Node {
constructor(isWord = false) {
this.isWord = isWord;
this.next = new Map();
}
}
class Trie {
constructor() {
this.root = new Node();
}
add(key) {
let cur = this.root;
for (let i = 0; i < key.length; i++) {
const c = key[i];
if (!cur.next.get(c)) {
cur.next.set(c, new Node());
}
cur = cur.next.get(c);
}
}
match(prefix) {
if (prefix === "") {
return [];
}
let cur = this.root;
const res = [];
for (let i = 0; i < prefix.length; i++) {
const c = prefix[i];
if (!cur.next.get(c)) {
return [];
}
res.push(prefix.slice(0, i + 1));
cur = cur.next.get(c);
}
return res;
}
}
const trie = new Trie();
function add(address) {
for (let i = 0; i < address.length; i++) {
trie.add(address[i].id);
if (address[i].children) {
add(address[i].children);
}
}
}
add(address);
trie.match("112"); // [1,11,112]
trie.match("111"); // [1,11,111]
trie.match("11"); // [1,11]
trie.match("110"); // []
发布评论
评论(58)
评论好多直接复制黏贴都是错的,发之前先测试一下啊,另外如果按照示例中省市区id的规则,可以找到目标 id 然后直接推倒出所有父 id 的吧....
const value = '112'
const fn = (value) => {
let vals = value.split('');
//1 11 112
for (let i = 0; i < vals.length; i++) {
let v = vals.slice(0,i+1).join('')
console.log(v)
}
}
fn(value)
仔细看了下题目意图应该是通过这个id值 解析出所有父级链路,但是根据数据截图,这样推演下去34个省 可能会出现 3411 34512 这就没法玩了 省应该至少占两位 01 - 34 ; 为了出题而出的题 ,没有实用价值
经典数据结构的深度遍历结构
为什么运行结果不对
@wangyuanyuan0521
@ZodiacSyndicate
源码
测试
解释
用途:用来把地址串转换为地址数组,常用于地址选择器,这里支持任何方式分割(常用于6 位地址每两位分割一次)
原理很简单,字符串是有规律的(每个更详细串包含父级串),就是简单的字符串分割(循环每次取前radix*(idx+1)范围的子串)
其实我也想问这个问题:
思路:
1、将数组转换为多个一维数组,结果如下所示:
2、循环第一步所得的结果,判断最后一位是不是和要查询的id相同,如果是那么就返回结果
为了可读性,牺牲了部分复杂度。
代码:
刚好有类似需求,试完答案竟然基本都是错的,自己试试。
不知道这样可以不
思路是每次遍历之前都利用结构记录一下层级,如果知道对应的id,直接返回即可
`const list = [{
id: '1',
name: '广东省',
children: [{
id: '11',
name: '深圳市',
children: [{
id: '111',
name: '南山区'
},
{
id: '112',
name: '福田区'
}
]
}]
}]
const value = '112'
const fn = (value, list) => {
let queue = [...list], res = [], level = 0
while(queue.length) {
debugger
let length = queue.length
for (let i = 0; i < length; i++) {
let node = queue.shift()
if (node.id === value) {
res.push(node.id)
} else {
if (value.slice(0, level + 1) === node.id) {
res.push(node.id)
}
node.children && queue.push(...node.children)
}
}
level++
}
}
console.log(fn(value, list))`
广度优先遍历
if (node.id === value) {
temp.push(node.id)
res = temp
return
}
const info = [{ id: '1', name: '广东省', children: [{ id: '11', name: '深圳市', children: [{ id: '111', name: '南山区', }, { id: '112', name: '福田区' }] }] }]; const fn = (value) => { let res = null; const dfs = (data, path) => { data.forEach((item) => { if (item.id === value) { path.push(item.id); res = path; return; }; if (item.children) { path.push(item.id); dfs(item.children, path); } }); }; dfs(info, []); return res; };
`var list = [{
id: '1',
children: [{
id: '11',
children: [{
id: '111'
}, {
id: '112'
}]
}, {
id: '12',
children: [{
id: '121'
}, {
id: '122'
}]
}]
}]
let result = [];
function findParentId(list2, val) {
for (let key of list2) {
console.log(key)
if (key.id === val) {
result.push(key.id);
return result;
}
if (key.children) {
result.push(key.id);
let re = findParentId(key.children, val);
if (re && re.length) {
return re;
} else {
result.pop();
}`
function fnBFS(list, target) {
let resMap = {}
console.log(resMap)
let res = ''
while(resMap[target]) {
res +=
${target} ->
target = resMap[target]
if(!resMap[target]) {
res += target
}
}
console.log(res)
}
前缀树 Trie,复杂度仅为需要查找value的长度:
let list = [{
id: '1',
value: '四川省',
children: [{
id: '11',
value: '成都市',
children: [{
id: '111',
value: '高新区'
}, {
id: '112',
value: '天府新区'
}]
}]
}, {
id: '2',
value: '四川省',
children: [{
id: '21',
value: '成都市',
children: [{
id: '211',
value: '高新区'
}, {
id: '212',
value: '天府新区'
}]
}]
}];
function fn(list, id) {
let res = []
function search(list, res) {
let searched = false;
for (let node of list) {
if (node.id === id) {
res.push(node.id)
return true
} else {
if (node.children) {
res.push(node.id)
searched = search(node.children, res);
if (searched) {
return true
}
}
}
}
if (!searched) {
res.pop()
return false
}
}
search(list, res);
return res
}
console.log(fn(list, '212'))
const find04 = (arr, val) => {
let carr = {}
let func = (list, label) => {
list.forEach((item, index) => {
if (carr[label]) {
carr[item.id] = carr[label] + ',' + item.id
} else {
carr[item.id] = item.id
}
if (item.children && item.children.length > 0) {
}
这好像没提前返回吧?找到了不需要继续递归了
// 跟之前总结的树路径查找一个道理
dfs + 回溯
dfs
---> 1 13 131
回朔法
深度优先
简单的回溯,找到之后停止继续查找
写法是深度优先, 增加了数据结构的深度与广度,能可以正确输出
刚刚好,中间仅仅差了一个数组方法:
@ZodiacSyndicate
这个写法想查112的时候不就查不出来了..
嗯我再研究一下~
这个情景不太对吧
思路是找到子节点,再回溯找父节点
复杂度是O(n),循环n次子节点,但是需要额外空间记录父节点引用
dfs