Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >网格中最短路径的算法

网格中最短路径的算法
EN

Stack Overflow用户
提问于 2020-01-24 17:40:26
回答 1查看 799关注 0票数 0

背景:

问题来自于leetcode

在N×N平方网格中,每个单元格要么是空的(0),要么是阻塞的(1)。 从左上角到右下角的清晰路径具有长度k当且仅当它是由单元格C_1, C_2, ..., C_k组成的,这样:

  • 相邻的信元C_iC_{i+1}是向8方向连接的(也就是说,它们是不同的,并且共享一个边或角)。
  • C_1(0, 0)的位置。有价值的grid[0][0])
  • C_k(N-1, N-1)的位置。有价值的grid[N-1][N-1])
  • 如果C_i位于(r, c),那么grid[r][c]是空的。grid[r][c] == 0)。

从左上角到右下角返回最短的这种清晰路径的长度。如果不存在这样的路径,则返回-1。

问题:

我确信我的算法是正确的,但是对于这个测试用例:

代码语言:javascript
运行
AI代码解释
复制
[[0,1,0,0,0],[0,1,0,0,0],[0,0,0,0,1],[0,1,1,1,0],[0,1,0,0,0]]

我得到9,正确的答案是7。下面的代码中有我做错了什么吗?

代码:

代码语言:javascript
运行
AI代码解释
复制
class Solution {
public:
    std::vector<std::vector<int>> dirs = {{0,1},{1,0},{-1,0},{0,-1},{1,1},{-1,-1},{1,-1},{-1,1}};
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        if(grid.empty())
            return 0;

        if(grid[0][0] == 1 || grid[grid.size()-1][grid.size()-1] == 1) 
            return -1;


        int m = grid.size(), n = grid[0].size();
        std::pair<int, int> start = {0,0};
        std::pair<int, int> end = {m-1, n-1};
        std::vector<std::vector<bool>> visited(m, std::vector<bool>(n, false));
        std::priority_queue<std::pair<int,int>> q;
        q.push(start);
        visited[start.first][start.second] = true;
        int count = 1;

        while(!q.empty())
        {
            auto cur = q.top();
            q.pop();

            if(cur.first == end.first && cur.second == end.second)
                return count;

            for(auto dir : dirs)
            {
                int x = cur.first, y = cur.second;

                if(isValid(grid, x + dir[0], y + dir[1]))
                    x += dir[0], y += dir[1];

                if(!visited[x][y])
                {
                    visited[x][y] = true;
                    q.push({x,y});
                }
            }
            count++;
        }
        return -1;
    }

    bool isValid(std::vector<std::vector<int>>& grid, int i, int j)
    {
        if(i < 0 || i >= grid.size() || j < 0 || j >= grid[i].size() || grid[i][j] != 0)
            return false;
        return true;
    }
};
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-25 02:55:48

对于这个问题,您可以使用Dijkstra的算法。这个算法是处理加权图,而你正在处理的问题是不加权的。此外,使用优先级队列的方式是错误的。默认情况下,C++优先级队列将弹出最大的元素,但由于提供了它的坐标,这意味着它将弹出具有最大坐标的元素。这显然不是你需要的。实际上,您没有任何可以排序的节点,因为这个问题是关于一个未加权图的。

其次,count正在计算您访问的节点总数。这是不对的,因为您当然也访问了那些不是在您最终找到的最短路径上的节点。

这种问题是用标准的深度优先搜索来解决的。您可以使用两个向量(不需要堆栈、队列或deque,.):第二个向量由第一个节点中所有节点的未访问邻居填充。这个循环完成后,用第二个向量替换第一个向量,创建一个新的第二个向量,然后重复.直到你找到目标节点。执行此(外部)重复的次数与路径的长度相对应。

下面是您的shortestPathBinaryMatrix函数,需要进行必要的调整,以使其正常工作:

代码语言:javascript
运行
AI代码解释
复制
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
    if(grid.empty())
        return 0;

    if(grid[0][0] == 1 || grid[grid.size()-1][grid.size()-1] == 1) 
        return -1;

    int m = grid.size(), n = grid[0].size();
    pair<int, int> start = {0,0};
    pair<int, int> end = {m-1, n-1};
    vector<vector<bool>> visited(m, vector<bool>(n, false));
    // no priority queue needed: the graph is not weighted
    vector<std::pair<int,int>> q;
    q.push_back(start);
    visited[start.first][start.second] = true;
    int count = 1;

    while(!q.empty())
    {
        // just iterate the vector and populate a new one
        vector<std::pair<int,int>> q2;
        for(auto const& cur: q) {
            if(cur.first == end.first && cur.second == end.second)
                return count;
            for(auto dir : dirs)
            {
                int x = cur.first, y = cur.second;

                if(isValid(grid, x + dir[0], y + dir[1]))
                    x += dir[0], y += dir[1];

                if(!visited[x][y])
                {
                    visited[x][y] = true;
                    q2.push_back({x,y});
                }
            }
        }
        count++;
        q = q2; // prepare for next iteration
    }
    return -1;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59905657

复制
相关文章
为什么是AUC值而不是GSEA来挑选转录因子呢
通过学习,我们知道这个RcisTarget包内置的motifAnnotations_hgnc是16万行,可以看到每个基因有多个motif。而且下载好的 hg19-tss-centered-10kb-7species.mc9nr.feather 文件,也是 24453个motifs的基因排序信息。但是我们留下来了一个悬念,如何从几万个注释结果里面挑选到最后100个富集成功的motif呢?
生信技能树
2020/12/03
1.3K0
为什么是AUC值而不是GSEA来挑选转录因子呢
为什么 C# 的 string.Empty 是一个静态只读字段,而不是一个常量呢?
使用 C# 语言编写字符串常量的时候,你可能会发现可以使用 "" 而不能使用 string.Empty。进一步可以发现 string.Empty 实际上是一个静态只读字段,而不是一个常量。
walterlv
2020/02/10
1.1K0
innodb为什么选择B+ Tree而不是跳表,Redis为什么选择跳表而不是B+ Tree
链表和数组相比,数组可以通过下标快速定位,或者通过二分查找,查询复杂度为O(logn),而链表只能按照顺序挨个查找,复杂度为O(n)。
大忽悠爱学习
2023/03/23
2.5K0
innodb为什么选择B+ Tree而不是跳表,Redis为什么选择跳表而不是B+ Tree
js判断list的某一个值是不是存在
最近更新博客的频率确实是慢了很多,主要是事情比较多,确实也没时间更新。今天相对有点时间,所以简单记录一下一个比较常见的问题。
何处锦绣不灰堆
2020/05/29
2.5K0
面试题46:为什么Redis使用SDS而不是C字符串?
【说明】最后一位遵循C字符串的空字符('\0')结尾的规则,目的是,可以直接使用C字符串的函数。其中len计数不包含‘\0’。
爪哇缪斯
2023/05/09
2920
面试题46:为什么Redis使用SDS而不是C字符串?
Java处理包含引号的String字符串
背景 在开发默认提示文字时: 解决方案 转义 使用\"代替" 效果 正常
JavaEdge
2021/02/22
1.8K0
Java处理包含引号的String字符串
为什么建议你用nullptr而不是NULL?
在C语言中,我们常常用NULL作为指针变量的初始值,而在C++中,却不建议你这么做。
编程珠玑
2019/08/28
9.6K0
为什么建议使用你 LocalDateTime ,而不是 Date?
多线程并发如何保证线程安全 - 避免线程之间共享一个SimpleDateFormat对象,每个线程使用时都创建一次SimpleDateFormat对象 => 创建和销毁对象的开销大 - 对使用format和parse方法的地方进行加锁 => 线程阻塞性能差 - 使用ThreadLocal保证每个线程最多只创建一次SimpleDateFormat对象 => 较好的方法
芋道源码
2019/10/23
1.6K0
JDBC为什么要使用PreparedStatement而不是Statement
前言 这篇博客不是我写的,是由刘志军大大翻译的,真心觉得很棒,而且是必学要掌握的东西,所以就转载过来了,我个人的第一篇转载文章。 开始 PreparedStatement是用来执行SQL查询语句的API之一,Java提供了 Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程。同时Prepar
roobtyan
2018/06/04
1.5K0
为什么特征工程要用 SQL 而不是 Python
我们常说机器学习是一门实验科学。所以相比较传统工程而言,机器学习分成两个大的阶段:
用户2936994
2022/05/18
8610
为什么特征工程要用 SQL 而不是 Python
JDBC为什么要使用PreparedStatement而不是Statement
PreparedStatement是java.sql包下面的一个接口,用来执行SQL语句查询,通过调用connection.preparedStatement(sql)方法可以获得PreparedStatment对象。数据库系统会对sql语句进行预编译处理(如果JDBC驱动支持的话),预处理语句将被预先编译好,这条预编译的sql查询语句能在将来的查询中重用,这样一来,它比Statement对象生成的查询速度更快。下面是一个例子:
哲洛不闹
2018/09/19
9780
JDBC为什么要使用PreparedStatement而不是Statement
为什么我会选择 React 而不是 Vue?
你注意到我过于圆滑的标题了吗?我将依据我所喜欢的方式去构建这个对话,而不是我客观上认为的唇枪舌战。我想后者并不会起作用。
疯狂的技术宅
2019/03/27
1.4K0
JDBC为什么要使用PreparedStatement而不是Statement
PreparedStatement是java.sql包下面的一个接口,用来执行SQL语句查询,通过调用connection.preparedStatement(sql)方法可以获得PreparedStatment对象。数据库系统会对sql语句进行预编译处理(如果JDBC驱动支持的话),预处理语句将被预先编译好,这条预编译的sql查询语句能在将来的查询中重用,这样一来,它比Statement对象生成的查询速度更快。下面是一个例子:
哲洛不闹
2018/09/19
1.1K0
JDBC为什么要使用PreparedStatement而不是Statement
JDBC为什么要使用PreparedStatement而不是Statement
PreparedStatement是用来执行SQL查询语句的API之一,Java提供了 Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程。同时PreparedStatement还经常会在Java面试被提及,譬如:Statement与PreparedStatement的区别以及如何避免SQL
java达人
2018/01/31
3.8K0
为什么建议使用你LocalDateTime,而不是Date?
在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗?
良月柒
2019/10/28
1.5K0
为什么建议使用你LocalDateTime,而不是Date?
为什么建议使用你 LocalDateTime ,而不是 Date?
来源:juejin.im/post/5d7787625188252388753eae
JAVA葵花宝典
2019/10/29
1.1K0
为什么建议使用你 LocalDateTime ,而不是 Date?
来源:juejin.im/post/5d7787625188252388753eae
用户1516716
2019/10/24
1.1K0
为什么建议你使用LocalDateTime而不是Date?
calendar是共享变量,并且这个共享变量没有做线程安全控制。当多个线程同时使用相同的SimpleDateFormat对象【如用static修饰的SimpleDateFormat】调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。在多并发情况下使用SimpleDateFormat需格外注意SimpleDateFormat除了format是线程不安全以外,parse方法也是线程不安全的。parse方法实际调用alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了
Bug开发工程师
2020/03/12
2.1K0
为什么是int main()而不是void main()
这是基于我们学校老师一直使用void main(),而发的感慨,大一学习C语言时,我就在想,老师上课演示的为什么一直用void main(),而不是int main()呢?不为了偷懒?还是习惯性的语句呢?在查阅了部分大牛的博客,翻阅了C Primer Plus和C++ Primer Plus这两本圣经级别的书本之后,得出以下结论(有一部分是别人的结论,属于半转载),可能不太严谨,请多多包涵。
对弈
2019/09/04
3.7K0
为什么 url 通常使用域名而不是 IP 地址?
大家好,我是前端西瓜哥。今天来谈谈为什么我们的网址,通常是使用域名,而不是 IP 地址。
前端西瓜哥
2022/12/21
1.8K0

相似问题

从HTML表中获取数据更新MySQL数据库

20

从表中更新数据

14

更新表数据,从另一个表中获取

33

如何从包含要更新的基表中的数据的联接表中获取数据?

20

如何从XML中获取数据并更新数据库表

12
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档