算法学习记录(二十一)

87 阅读1分钟

问:

  1. 假设一个二维数组,元素只有0,1。若元素1的上下左右也是1,就当做是同一片1,称作一个岛。例如这个数组代表三片岛。如何求岛的数量
    const arr = [[1,0,1,1]
                 [1,0,0,0]
                 [1,1,1,1]
                 [1,1,0,1]]
    
  2. 并查集结构

解:

  1. 遍历数组,遇到1就把它变成2,并且递归感染相邻的1。
function getIsLandNum(arr) {
    let res = 0
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr[i].length; j++) {
            if (arr[i][j] === 1) {
                res++
                // 遇到1就感染它相邻的1
                infected(i, j)
            }
        }
    }
    function infected(i, j) {
        // 越界且不等于1直接返回
        if (i < 0 || i >= arr.length || j < 0 || j >= arr[i].length || arr[i][j] !== 1) return
        arr[i][j] = 2
        infected(i - 1, j)
        infected(i + 1, j)
        infected(i, j - 1)
        infected(i, j + 1)
    }
    return res
}
  1. 并查集
class MyNode {
    constructor(val) {
        this.value = val
        this.father = this
    }
}
class UnionFindSets {
    constructor(arr) {
        // node表
        this.nodeMap = new Map()
        // 集合大小表
        this.setSizeMap = new Map()
        // 遍历数组,所有数组每一项都转为node,每个node初始化都是一个集合,大小为1
        for (let i of arr) {
            const node = new MyNode(i)
            this.nodeMap.set(i, node)
            this.setSizeMap.set(node, 1)
        }
    }
    // 两个节点的顶层节点一致则为同一集合
    isSameSet(val1, val2) {
        if (!(this.nodeMap.has(val1) && this.nodeMap.has(val2))) return false
        return this.findLastNode(val1) === this.findLastNode(val2)
    }
    // 查询顶层元素
    findLastNode(val) {
        let node = this.nodeMap.get(val)
        const stack = []
        while (node.father) {
            stack.push(node)
            node = node.father
        }
        // 扁平化链表,沿途所有节点的father都指向顶层节点,避免链过长导致查询时间复杂度过高
        while (stack.length) {
            const pathNode = stack.pop()
            pathNode.father = node
        }
        return node
    }
    unionSet(val1, val2) {
        // 找到集合的顶层元素
        const last1 = this.findLastNode(val1)
        const last2 = this.findLastNode(val2)
        if (last1 && last2 && last1 !== last2) {
            // 将小的集合顶层元素的father指向大的集合顶层元素
            const size1 = this.setSizeMap.get(last1)
            const size2 = this.setSizeMap.get(last2)
            const big = size1 > size2 ? last1 : last2
            const small = big === last1 ? last2 : last1
            small.father = big
            this.setSizeMap.set(big, size1 + size2)
            this.setSizeMap.delete(small)
        }
    }
}