机器人大冒险

力扣团队买了一个可编程机器人,机器人初始位置在原点(0, 0)。小伙伴事先给机器人输入一串指令command,机器人就会无限循环这条指令的步骤进行移动。指令有两种:

U: 向y轴正方向移动一格
R: 向x轴正方向移动一格。
不幸的是,在 xy 平面上还有一些障碍物,他们的坐标用obstacles表示。机器人一旦碰到障碍物就会被损毁。

给定终点坐标(x, y),返回机器人能否完好地到达终点。如果能,返回true;否则返回false。

示例 1:

输入:command = “URR”, obstacles = [], x = 3, y = 2
输出:true
解释:U(0, 1) -> R(1, 1) -> R(2, 1) -> U(2, 2) -> R(3, 2)。
示例 2:

输入:command = “URR”, obstacles = [[2, 2]], x = 3, y = 2
输出:false
解释:机器人在到达终点前会碰到(2, 2)的障碍物。
示例 3:

输入:command = “URR”, obstacles = [[4, 2]], x = 3, y = 2
输出:true
解释:到达终点后,再碰到障碍物也不影响返回结果。

限制:

2 <= command的长度 <= 1000
command由U,R构成,且至少有一个U,至少有一个R
0 <= x <= 1e9, 0 <= y <= 1e9
0 <= obstacles的长度 <= 1000
obstacles[i]不为原点或者终点

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/programmable-robot
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

错误例子(运行超时):

class Solution {
    public boolean robot(String command, int[][] obstacles, int x, int y) {
        int currentX = 0;
        int currentY = 0;
        int temp = -1;
        while(currentX != x || currentY != y){
            temp = (temp+1) % command.length();
            if(command.charAt(temp) == 'U'){
                currentY++;
            } else {
                currentX++;
            }
            for(int i = 0;i < obstacles.length;i++){
                if(currentX == obstacles[i][0] && currentY == obstacles[i][1])
                    return false;
            }
        }
        return true;
    }
}

正确代码:

class Solution {
    public boolean robot(String command, int[][] obstacles, int x, int y) {
        int dx = 0, dy = 0;
        char[] cmd = command.toCharArray(); // 把String转为数组,方便遍历。
        for (char c : cmd) { // 算出up和right各有多少个。
            if (c == 'U') dy++;
            else dx++;
        }
        int ans = isPassed(cmd, x, y, dx, dy); // 拿到走到终点的次数。
        // 先看isPassed函数再往下看。
        /*
            为什么isPassed要拿到走的总次数而不直接返回true或false呢
            比如你发现有一个obstacle是经过的,那么最终答案并不一定是false,
            因为如果终点在这个点的前面,那么机器人根本不会走到那个点。答案是true。
        */
        if (ans == -1) return false; // 终点都没经过,肯定false
        for (int[] obstacle : obstacles) {
            int cnt = isPassed(cmd, obstacle[0], obstacle[1], dx, dy);
            if (cnt != -1 && cnt < ans) return false; 
            //不等于-1,说明经过了,然后再看这个点和终点哪个次数多。ans多,说明这个点在ans前面,返回false。
        }
        return true;
    }
    // 判断是否经过该点,经过返回走的次数,没经过返回-1。
    public int isPassed(char[] cmd, int x, int y, int dx, int dy) {
        int round = Math.min(x / dx, y / dy); // 计算走到第x-1或y-1层需要多少轮
        int cnt = cmd.length * round;  // 前几轮的总次数
        dx *= round; dy *= round; // 在第x-1或y-1层时的位置。
        if (dx == x && dy == y) return cnt; // 正好就是要找的点,直接返回。
        for (char c : cmd) { // 遍历第x层或y层,如果经过,那么答案一定会遍历到。
            if (c == 'U') dy++; // 要按command的顺序走
            else dx++;
            cnt++; // 不要忘了每遍历一次,次数都要加1
            if (dx == x && dy == y) return cnt; // 一旦找到,直接返回所需要的次数。
        }
        return -1;
    }
}

作者:ripple-4
链接:https://leetcode-cn.com/problems/programmable-robot/solution/chang-gui-fang-fa-xiang-xi-zhu-shi-si-lu-by-ripple/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
发布了18 篇原创文章 · 获赞 23 · 访问量 1392

猜你喜欢

转载自blog.csdn.net/qq_44329476/article/details/102888003