程序员面试金典 8.2

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;
        }
    }
};
发布了194 篇原创文章 · 获赞 2 · 访问量 7720

猜你喜欢

转载自blog.csdn.net/RayoNicks/article/details/105442359
今日推荐