程序员面试金典 8.2

本文介绍了一种在机器人迷宫中寻找从左上角到右下角路径的算法。通过优化重复计算,将时间复杂度从O(2^(r+c))降低到O(rc)。文章详细解释了如何避免重复计算,并提供了具体的实现代码。

Robot in a Grid:一个机器人在处在一个rc列的迷宫的左上角。机器人在每一个位置时只能向右或者向左移动,但是迷宫中有些格子是不能到达的。设计一个算法,为机器人找到一条从左上角到右下角的路径。

机器人最终到达rc列(用(r, c)表示),那么他肯定是从(r - 1, c)或者(r, c - 1)移动过来的,所以可以把问题转换为求解子问题:寻找一条终点为(r - 1, c)或者(r, c - 1)的路径。为了到达(r - 1, c),上一步可以在(r - 2, c)或者(r - 1, c - 1);为了到达(r, c - 1),上一步可以在(r - 1, c - 1)或者(r, c - 2),此时已经出现了重复计算。在不优化重复计算的情况下,算法的时间复杂度为O(2 ^ (r + c)),因为每一次有两种选择,而移动的次数为r + c

迷宫的大小为r * c,如果只访问每个格子一次,那么时间复杂度就可以降为O(rc)。在上面的例子中,对(r - 1, c - 1)进行了两次计算,所以可以将其结果保存下来,以节省第二次的重复计算。

如果把Visited[r][c] = true放在最后的if或者else中,只表明该点可达或者不可达时进行重复标记,而不是所有情况。书中只对不可达点进行了重复标记。在力扣上,只对可达点进行重复标记时间大概1000ms,只对不可达点进行重复标记时间大概30ms,对所有点进行重复标记时间大概15ms

class Solution {
public:
    vector<vector<int>> pathWithObstacles(vector<vector<int>>& obstacleGrid) {
        Visited.assign(obstacleGrid.size(), vector<bool>(obstacleGrid[0].size(), false));
        calculatePath(obstacleGrid, obstacleGrid.size() - 1, obstacleGrid[0].size() - 1);
        return Path;
    }
private:
    vector<vector<int>> Path;
    vector<vector<bool>> Visited;
    bool calculatePath(const vector<vector<int>> &obstacleGrid, const int r, const int c)
    {
        if(r < 0 || c < 0 || obstacleGrid[r][c] == 1) return false;
        if(Visited[r][c]) return false;
        else Visited[r][c] = true;
        vector<int> curr = { r, c };
        bool bOrigin = r == 0 && c == 0;
        if(bOrigin || calculatePath(obstacleGrid, r - 1, c) || calculatePath(obstacleGrid, r, c - 1)){
            Path.push_back(curr);
            return true;
        }
        else{
            return false;
        }
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值