算法学习记录(三十八)

103 阅读2分钟

问:

  1. 给一个字符串类型的数组arr,譬如arr=['b\cst','d','a\d\e','a\b\c']。每个字符串都是一个路径。把这些路径中蕴含的目录结构打印出来。子目录在父目录下面,并且后移两个空格。同级目录按字符升序。如下所示:
a
  b
    c
  d
    e
b
  cst
d
  1. 给定一个搜索二叉树的头结点head,请转化为一条有序的双向链表。并返回链表头结点
  2. 找到一颗二叉树中,最大的搜索二叉子树。返回其节点个数
  3. 给定一个整型矩阵,返回子矩阵的最大累加和

解:

  1. 生成前缀树。深度优先遍历前缀树即可。
function printCatalogue(arr) {
    class DiyNode {
        constructor(val, level) {
            this.value = val
            this.level = level
            this.childrenMap = new Map()
        }
    }
    for (let i = 0; i < arr.length;i++) {
        arr[i] = arr[i].split('\\')
    }
    const orNode = new DiyNode()
    // 遍历字符串数组。形成前缀树
    for (let i = 0; i < arr.length; i++) {
        let curNode = orNode
        for (let j = 0; j <arr[i].length;j++) {
            if (!arr[i][j]) continue
            if (curNode.childrenMap.has(arr[i][j])) {
                curNode = curNode.childrenMap.get(arr[i][j])
            } else {
                const temp = new DiyNode(arr[i][j], curNode.level + 1)
                curNode.childrenMap.set(arr[i][j], temp)
                curNode = temp
            }
        }
    }
    // 打印前缀树
    print(orNode.childrenMap)
    
    // 给前缀树的每一层按key排序
    function sortMap(map) {
        const keys = []
        for (let i of map.keys()) {
            keys.push(i)
        }
        keys.sort((a, b) => a.localeCompare(b))
        const sp = new Map()
        keys.forEach((item) => {
            sp.set(item, map.get(item))
        })
        return sp
    }
    // 深度优先打印
    function print(map) {
        if (!map) return
        map = sortMap(map)
        for (let i of map.entries()) {
            console.log(' '.repeat((i[1].level - 1) * 2) + i[0]);
            print(i[1].childrenMap)
        }
    }
}
function treeToList(head) {
    function getRes(node) {
        if (!node) return {min: null, max: null}
        const leftInfo = getRes(node.left)
        const rightInfo = getRes(node.right)
        if (leftInfo.max) leftInfo.max.next = node
        node.next = rightInfo?.min
        if (rightInfo.min) rightInfo.min.pre = node.next
        node.pre = leftInfo?.max
        return {
            min: leftInfo.min ?? node,
            max: rightInfo.max ?? node
        }
    }
    return getRes(head).min
}
function findMaxBs(head) {
    let max = 1
    function getRes(node) {
        if (!node) return {
            nums: 0,
            isBST: true,
            max: -Infinity,
            min: Infinity
        }
        const leftInfo = getRes(node.left)
        const rightInfo = getRes(node.right)
        // 如果左右子树都是bst
        if (leftInfo.isBST && rightInfo.isBST) {
            // 若当前节点也符合bst
            if (node.val > leftInfo.max && node.val < rightInfo.min) {
                const nums = leftInfo.nums + rightInfo.nums + 1
                max = Math.max(max, nums)
                return {
                    nums,
                    isBST: true,
                    min: leftInfo.min === Infinity ? node.val : leftInfo.min,
                    max: rightInfo.max === -Infinity ? node.val : rightInfo.max
                }
            }
        }
        // 否则不是bst
        return {
            isBST: false
        }
    }
    getRes(head)
    return max
}
function getMaxSum(Matrix) {
    let maxSum = -Infinity
    // 矩阵的最大子矩阵和。可以分解为若干矩阵累加成一个数组的最大子序和问题
    // 也就是说像
    // matrix=[[1,2,3,4]
    //        [2,3,4,5]
    //        [-1,-2,3,-4]]
    // 这种矩阵。可以分解为
    // 只看第i行。求第i行子序和问题。
    // 只看第i~n行。求第i~n行子矩阵问题
    // 第i~n行,可以用矩阵累加方式转换成数组。也就等同于数组子序和问题
    // 譬如第0~1行矩阵 同列相加,转换成数组[3,5,7,9]

    for (let i = 0; i < Matrix.length; i++) {
        let preArrSum = []
        for (let j = i; j < Matrix.length; j++) {
            for (let k = 0; k < Matrix[i].length; k++) {
                preArrSum[k] = (preArrSum[k] ?? 0) + Matrix[j][k]
            }
            const tempMax = getArrSum(preArrSum)
            maxSum = Math.max(maxSum, tempMax)
        }
    }
    // 最大子序和
    function getArrSum(arr) {
        let sum = 0
        let max = -Infinity
        for (let i of arr) {
            sum += i
            max = Math.max(max, sum)
            if (sum < 0) sum = 0
        }
        return max
    }
    return maxSum
}