算法学习记录(十五)

114 阅读2分钟

问:

  1. dijkstra算法求最小路径
  2. 给定一个字符串数组,查询某字符串出现次数、以该字符串为前缀的字符串有多少。 解:
  3. 先假定一个目标节点与其他节点的距离无穷大并记录进哈希表,找到哈希表中距离最小的节点,然后遍历这个节点的所有边,如果通过这条路线使得目标到其他点的距离有小于哈希表中存的值,那么就更新哈希表中的数据。
    function dijkstra(graph) {
        const nodes = graph.nodes
        // 随便选一个点作为观察对象
        const targetNode = nodes[0]
        const targetMap = new Map()
        const edgesSet = new Set()
        const choosedNode = new Set()
        // 设定这个点到其他所有点的距离为无穷大
        nodes.forEach((item) => {
            targetMap.set(item, item === targetNode ? 0 : Infinity)
        })
        // 选取最小距离的节点
        let minNode = getMinDisNode(targetMap, choosedSet)
        while (minNode) {
            const edges = minNode.edges
            edges.forEach(item => {
                // 排除重复边
                if (!edgesSet.has(item)) {
                    edgesSet.add(item)
                    // 若target表记录的距离大于当前路线的距离,就更新target记录表
                    const oldDistance = targetMap.get(item.to)
                    const curDistance = item.weight + value
                    targetMap.set(item.to, Matn.min(oldDistance, curDistance))
                    choosedSet.add(minNode)
                    minNode = getMinDisNode(targetMap, choosedSet)
                }
            })
        }
        return targetMap
    }
    function getMinDisNode(targetMap, choosedSet) {
        let minDis = Infinity
        for (let [key, val] of targetMap.entries()) {
            if (!choosedSet.has(key) && val < minDis) {
                return key
            }
        }
        return null
    }
  1. 先生成一个root节点,遍历strArr中的每一个字符串,再遍历字符串的每一个字符,当前节点指向root节点,若当前节点没有遍历到的字符时,就给当前节点生成对应的字符节点,并记录该字符节点pass+1,当前节点指向新节点。若这个字符是字符串的最后一位,就给字符节点记录end+1。
    const strArr = ['icytail', 'icy', 'tail', '哈哈', '哈呵']
    // 字符串节点
    class StrNode {
        constructor() {
            this.pass = 0
            this.end = 0
            this.charMap = new Map()
        }
        newCharNode (char) {
            this.charMap.set(char, new StrNode())
        }
        isHasChar (char) {
            return this.charMap.has(char)
        }
        getCharNode (char) {
            return this.charMap.get(char)
        }
    }
    function preTree(strArr) {
        const rootNode = new StrNode()
        for (let str of strArr) {
            let curNode = rootNode
            // 路过顶层节点次数+1,表明有多少个字符串进来过
            curNode.pass += 1
            for (let i = 0; i < str.length; i++) {
                const char = str[i]
                // 如果没有过这个字符
                if (!curNode.isHasChar(char)) {
                    // 给当前节点创建一条新节点,并且cur指向这个新节点
                    curNode.newCharNode(char)
                }
                // 当前节点指向这个字符节点
                curNode = curNode.getCharNode(char)
                // 这个字符节点出现次数+1
                curNode.pass += 1
                // 如果是字符串结尾,那么该字符节点end+1
                if (i === str.length - 1) curNode.end += 1
            }
        }
        return rootNode
    }
    function searchCharPreNum(str, trie) {
        let curNode = trie
        let res = 0
        for (let i = 0; i < str.length; i++) {
            const char = str[i]
            if (curNode.isHasChar(char)) {
                curNode = curNode.getCharNode(char)
                // 遍历到当前字符串的最后一位,那么pass值就是出现过多少次该字符串
                if (i === str.length -1) res = curNode.pass
            } else {
                break
            }
        }
        return res
    }