[LeetCode 得分最高的路径] | 刷题打卡

573 阅读2分钟

1102. 得分最高的路径

leetcode-cn.com/problems/pa…

  • 先排序 然后并查集 。按照格子值从大到小进行遍历,没读取一个格子,就把格子进行染色,用二维数组来表示已经染色的格子集合,然后检查该格子的上下左右是否也经过染色,如果也染过色,那么将该格子加入到同一个并查集里。直到第一个格子和最后一个格子属于同一个并查集

    • 初始化最大值为格子首元素的值和最后一个元素的最小值;
    • 将格子中元素按值从小到大排序;
    • 每次取队列尾元素染色,如果周围也被染色,就将该格子与邻近格子集合合并,更新最大值为已经染色的元素的最小值;
    • 直到第一个格子和最后一个格子在一个集合中,返回最大值
/**
 * @param {number[][]} A
 * @return {number}
 */
var maximumMinimumPath = function(A) {
    const dirctions = [[0,1],[1,0],[-1,0],[0,-1]]
    const width = A.length
    const height = A[0].length
    
    const n = width * height

    const djs = new DisJointSet(n)

    let maxVal = Math.min(A[0][0],A[width-1][height-1])

    let queue = []

    for(let i=0;i<width;i++){
        for(let j=0;j<height;j++){
            queue.push([i,j,A[i][j]])
        }
    }
    queue = queue.sort((a,b) => a[2] - b[2])
    // 保存元素是否被染色的信息
    const colorSet = A.map(item=>item.map(_=>0))
    // 若是第一个格子和最后一个格子联通 则结束循环
    while(!djs.isConnected(0,n-1)){
        const [x,y,val] = queue.pop()
        maxVal = Math.min(val,maxVal)
        colorSet[x][y] = 1
        dirctions.forEach(dir=>{
            const nowX = dir[0] + x
            const nowY = dir[1] + y
            if(nowX >=0 && nowY >=0 && nowX <width && nowY<height && colorSet[nowX][nowY]===1){
            	// 当前格子在并查集中的index = x * height + y
                // 合并相邻的元素
                djs.merge(x * height + y,nowX * height + nowY)
            }
        })

    }
    return maxVal

};

class DisJointSet {

    rank = []
    parent = []

    constructor(size){
        for(let i=0;i<size;i++){
            this.parent[i] = i
            this.rank[i] = 1
        }
    }
    // 找出节点p的顶点 也就是所属的集合
    find(p){
        if(p<0 || p>(this.parent.length-1)){
            throw new Error("invalid element")
        }
        while(this.parent[p] !==p){
            // 路径压缩 在找的过程中将树的高度剪低
            this.parent[p] = this.parent[this.parent[p]]
            p = this.parent[p]
        }
        return p
    }
    merge(p,q){
        let pRoot = this.find(p)
        let qRoot = this.find(q)
        if(pRoot === qRoot){
            return
        }
        // 基于rank的优化 将高度较小的树嫁接到高度高的树 防止在合并的过程中树的高度增加
        if(this.rank[pRoot] < this.rank[qRoot]){
            this.parent[pRoot] = qRoot
        }else if(this.rank[pRoot] > this.rank[qRoot]){
            this.parent[qRoot] = pRoot
        }else{
            this.parent[qRoot] = pRoot
            this.rank[pRoot] ++ 
        }
    }
    // 并查集大小
    getsize(){
        return this.parent.length
    }
    // 两个集合是否联通
    isConnected(p,q){
        return this.find(p) === this.find(q)
    }

}