js算法:获取可能的路径

提问

给了以下点和路径,选取一点输出所有可能走过的点,走过的点不能重复
比如选取a,输出 [[a,b,c],[a,c,b,d,f],[a,b,d,e],…]**
js算法:获取可能的路径

设计数据格式

class Point {
  name = "";
  neighbor: string[] = [];
}
cosnt data: Point[] = [
  { name: "a", neighbor: ["b", "c"] },
  { name: "b", neighbor: ["a", "c", "d"] },
  { name: "c", neighbor: ["a", "b"] },
  { name: "d", neighbor: ["b", "e", "f", "g"] },
  { name: "e", neighbor: ["d"] },
  { name: "f", neighbor: ["d"] },
]

每一个点用Point类表示,name代表点的名字,neighbor表示该点的邻居

实现过程思路

一组走过的点使用string[]表示
实现一个方法,传入一个target,即点的name,返回所有可能走过的点的组合string[][]。(history参数下面会说到)

type getPath = (target: string, history?: string[]) => string[][];

比如我们从a开始,下一个点可能是b或者c,将会有两种分支。目前我们走的这组点为[‘a’],那么走下一步的时候我们要复制一下我们走过的点的组合,即复制成两个[‘a’]。多个分支复制成多个。那么[‘a’]就是下一次递归的history参数。

然后假设我们现在走过的是[‘a’, ‘b’],下一个点就不能有a了,也就是b点此时可选的邻居是[‘c’, ‘d’]。
实现一个方法,传入走过的点的组合,返回可选的下一个点

type getNext = (history: string[]) => string[];

如果下一步没路走了,也就代表我们找到一组可以走的点。

我们走了一步(target),得到当前走过的点(history),并且也知道下一步可以走哪(getNext),那么接下来就是用getPath进行递归。

具体实现

export class Point {
  name = "";
  neighbor: string[] = [];
}

export default class PathService {
  constructor(props: Point[]) {
    this.data = this.deepCopy(props);
  }

  data: Point[] = [];

  getData() {
    return this.deepCopy(this.data);
  }

  setData(pointList: Point[]) {
    this.data = this.deepCopy(pointList);
    this.resList = [];
  }

  resList: string[][] = [];

  getResList(): string[][] {
    const res: string[][] = [];
    for (const v of this.resList) {
      res.push([...v]);
    }
    return res;
  }

  /**
   * 深拷贝一个Point[]
   * @param pointList
   */
  deepCopy(pointList: Point[]): Point[] {
    const result: Point[] = [];
    for (const v of pointList) {
      result.push({
        name: v.name,
        neighbor: [...v.neighbor],
      });
    }
    return result;
  }

  /**
   * 获取下一次可选路径
   * @param historyArr 已走过的路径
   */
  getNext(historyArr: string[]): string[] {
    let nextData: string[] = [];
    // 获取刚走过的点
    const target = this.data.find(
      (v) => v.name === historyArr[historyArr.length - 1]
    );
    // console.log(target);
    if (target) {
      nextData = target.neighbor;
    }
    // 将走过的点过滤掉
    nextData = nextData.filter((v) => historyArr.indexOf(v) === -1);
    // // console.log(nextData)
    return nextData;
  }

  /**
   * 输入其实目标,获取
   * @param target
   * @param history
   */
  getPath(target: string, history?: string[]): string[][] {
    // console.log(target);
    let nextHistory: string[] = [];
    if (history) {
      // console.log(history);
      nextHistory = [...history];
    }
    // 先走一步
    nextHistory.push(target);
    // console.log('nextHistory', nextHistory)
    // 下一步能走哪呢
    const targetNavigation = this.getNextData(nextHistory || []);
    // console.log("targetNavigation", targetNavigation);
    // 没路走了
    if (targetNavigation.length === 0) {
      this.resList.push(nextHistory);
    }
    // 还有路走,可走的分支进行递归
    for (const v of targetNavigation) {
      this.getPath(v, nextHistory);
    }

    // 递归结束,全在this.resList里存好了
    return this.getResList();
  }
}

测试

    const data: Point[] = [
      { name: "a", neighbor: ["b", "c"] },
      { name: "b", neighbor: ["a", "c", "d"] },
      { name: "c", neighbor: ["a", "b"] },
      { name: "d", neighbor: ["b", "e", "f", "g"] },
      { name: "e", neighbor: ["d"] },
      { name: "f", neighbor: ["d"] },
    ];
    let pathService = new PathService(data);
    let result = pathService.getPath("a");
    console.log(result);

js算法:获取可能的路径

上一篇:LeetCode——滑动谜题


下一篇:BGP学习笔记 GoBGP资料归档