菜鸟什么时候才能变成老鸟,欢迎留言纠错~|

Shie1d

园龄:5年9个月粉丝:6关注:0

2617. 网格图中最少访问的格子数(困难)

核心思想
比较直观的想法就是BFS,但是每次遍历能走的点(右走,下走)会超时
考虑用两个set数组,
TreeSet<Integer>[] R = new TreeSet[n]; TreeSet<Integer>[] C = new TreeSet[m];
R[i]表示第i行还剩下哪些列col没去过,那么遍历就变为了二分查找第一个比当前j大的col
col > j + grid[i][j]时break

代码

public int minimumVisitedCells(int[][] grid) {
        // n 行 m 列
        int n = grid.length, m = grid[0].length;
        //存储步数
        int[][] f = new int[n][m];
        // 使用双重循环来填充二维数组
        for (int i = 0; i < n; i++) {
            Arrays.fill(f[i], -1);
        }
        TreeSet<Integer>[] R =  new TreeSet[n];
        TreeSet<Integer>[] C =  new TreeSet[m];
        for(int i = 0; i < n; i++)
            R[i] = new TreeSet<Integer>();
        for(int j = 0; j < m; j++)
            C[j] = new TreeSet<Integer>();
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(i + j > 0){
                    R[i].add(j);
                    C[j].add(i);
                }
            }
        }
        Queue<int[]> q = new ArrayDeque<>();
        q.offer(new int[]{0, 0});
        f[0][0] = 1;
        while(!q.isEmpty()){
            int[] tp = q.poll();
            int i = tp[0], j = tp[1];
            // 向右走 去R中找
            // 第一个大于j的数
            Integer ceil = R[i].ceiling(j);
            if(ceil != null){
                //最远距离
                int maxiCol = j + grid[i][j];
                Iterator<Integer> iterator = R[i].tailSet(ceil).iterator();
                while(iterator.hasNext()){
                    int col = iterator.next();
                    if (col > maxiCol)
                        break;
                    //记录步数
                    f[i][col] = f[i][j] + 1;
                    //推入队列
                    q.offer(new int[]{i, col});
                    //移出Set
                    iterator.remove();
                    C[col].remove(i);

                }
            }
            // 向下走 去C中
            // 第一个大于i的数
            ceil = C[j].ceiling(i);
            if(ceil != null){
                //最远距离
                int maxiRow = i + grid[i][j];
                Iterator<Integer> iterator = C[j].tailSet(ceil).iterator();
                while(iterator.hasNext()){
                    int row = iterator.next();
                    if(row > maxiRow)
                        break;
                    //记录步数
                    f[row][j] = f[i][j] + 1;
                    //推入队列
                    q.offer(new int[]{row, j});
                    //移出Set
                    iterator.remove();
                    R[row].remove(j);
                }
            }
        }
        return f[n-1][m-1];
    }

本文作者:Shie1d

本文链接:https://www.cnblogs.com/ganyq/p/18109113

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Shie1d  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起