leetcode
leetcode 1851 ~ 1900
执行所有后缀指令

执行所有后缀指令

难度:

标签:

题目描述

现有一个 n x n 大小的网格,左上角单元格坐标 (0, 0) ,右下角单元格坐标 (n - 1, n - 1) 。给你整数 n 和一个整数数组 startPos ,其中 startPos = [startrow, startcol] 表示机器人最开始在坐标为 (startrow, startcol) 的单元格上。

另给你一个长度为 m 、下标从 0 开始的字符串 s ,其中 s[i] 是对机器人的第 i 条指令:'L'(向左移动),'R'(向右移动),'U'(向上移动)和 'D'(向下移动)。

机器人可以从 s 中的任一第 i 条指令开始执行。它将会逐条执行指令直到 s 的末尾,但在满足下述条件之一时,机器人将会停止:

  • 下一条指令将会导致机器人移动到网格外。
  • 没有指令可以执行。

返回一个长度为 m 的数组 answer ,其中 answer[i] 是机器人从第 i 条指令 开始 ,可以执行的 指令数目

 

示例 1:

输入:n = 3, startPos = [0,1], s = "RRDDLU"
输出:[1,5,4,3,1,0]
解释:机器人从 startPos 出发,并从第 i 条指令开始执行:
- 0: "RRDDLU" 在移动到网格外之前,只能执行一条 "R" 指令。
- 1:  "RDDLU" 可以执行全部五条指令,机器人仍在网格内,最终到达 (0, 0) 。
- 2:   "DDLU" 可以执行全部四条指令,机器人仍在网格内,最终到达 (0, 0) 。
- 3:    "DLU" 可以执行全部三条指令,机器人仍在网格内,最终到达 (0, 0) 。
- 4:     "LU" 在移动到网格外之前,只能执行一条 "L" 指令。
- 5:      "U" 如果向上移动,将会移动到网格外。

示例 2:

输入:n = 2, startPos = [1,1], s = "LURD"
输出:[4,1,0,0]
解释:
- 0: "LURD"
- 1:  "URD"
- 2:   "RD"
- 3:    "D"

示例 3:

输入:n = 1, startPos = [0,0], s = "LRUD"
输出:[0,0,0,0]
解释:无论机器人从哪条指令开始执行,都会移动到网格外。

 

提示:

  • m == s.length
  • 1 <= n, m <= 500
  • startPos.length == 2
  • 0 <= startrow, startcol < n
  • s'L''R''U''D' 组成

代码结果

运行时间: 64 ms, 内存: 16.1 MB


/*
 * 思路:
 * 使用Java Stream从每个起始指令开始进行迭代,计算每个起始点的最大可执行指令数。
 * 使用流操作来简化代码,使用mapToInt将每个结果转化为int数组。
 */
import java.util.stream.IntStream;

public int[] executeInstructions(int n, int[] startPos, String s) {
    return IntStream.range(0, s.length()).map(i -> {
        int row = startPos[0], col = startPos[1];
        int count = 0;
        for (int j = i; j < s.length(); j++) {
            switch (s.charAt(j)) {
                case 'R': col++; break;
                case 'L': col--; break;
                case 'U': row--; break;
                case 'D': row++; break;
            }
            if (row < 0 || row >= n || col < 0 || col >= n) {
                break;
            }
            count++;
        }
        return count;
    }).toArray();
}

解释

方法:

题解首先遍历一次指令字符串s,计算出机器人每执行一步后的坐标。然后再反向遍历字符串s,同时更新两个字典d_x和d_y,这两个字典用来记录机器人到达某个x或y坐标的最新指令计数。在反向遍历过程中,通过比较当前位置与边界的关系,使用这两个字典来确定从当前位置开始,机器人能够执行的最大指令数。对于每个起始指令位置,计算出从该位置开始直到结束或出界的可执行指令数,并存储在结果数组ans中。

时间复杂度:

O(m)

空间复杂度:

O(m)

代码细节讲解

🦆
在反向遍历字符串`S`的过程中,为什么需要使用两个字典`d_x`和`d_y`来分别记录机器人到达某个x或y坐标的最新指令计数?
在反向遍历过程中,使用`d_x`和`d_y`字典记录机器人到达每个x和y坐标的最新指令计数的原因是为了快速确定机器人从当前位置起能够继续移动的最大步数,直到它可能移出边界。这样做可以有效地避免重复计算同一位置的最大可移动步数,提高算法效率。当机器人再次访问同一个x或y坐标时,可以直接使用字典中存储的最新指令计数来判断从该位置开始的最大可执行步数,从而减少不必要的计算。
🦆
如何确保字典`d_x`和`d_y`在记录过程中不会因为多个不同的坐标映射到相同的键而互相覆盖?
在本题中,每个x和y坐标值的范围是确定的,从`0`到`n-1`,因此不会出现多个不同的坐标映射到相同键的情况。每次机器人到达一个新的x或y坐标,字典`d_x`或`d_y`会更新或添加该坐标对应的指令计数。由于是反向遍历,每个坐标的最新指令计数总是最先被记录,确保了字典的准确性和数据不会被错误覆盖。
🦆
在算法中如何处理机器人移动到网格边界之外的情况,具体是怎样判断并计算机器人停止的位置?
在题解中,通过检查机器人每次移动后的坐标是否超出了网格的边界来处理机器人可能移出边界的情况。具体实现中,用`d_x`和`d_y`字典存储每个x和y坐标的最新指令计数,并在每次移动后检查该坐标是否已经存在于字典中。如果存在,比较当前步数与字典中存储的步数,计算出从当前位置开始到可能移出边界的最大指令数。通过这种方式,算法能够有效地判断并计算机器人在遇到边界时的停止位置。
🦆
题解中提到的`第二次反向遍历`是如何确保计算从每个位置开始能执行的最大指令数的准确性的?
第二次反向遍历通过从字符串的末尾开始,逐步向字符串开头遍历,可以确保每个位置的最大指令数是准确计算的。这种方式利用了动态规划的思想,即从已知的结果(边界或先前计算的结果)推导出当前问题的解。通过记录每个坐标点的最新指令计数,并结合边界检查,可以确保每次计算都是基于当前最可能的最大可执行步数。这样的逆序遍历确保了每个起始位置的指令计数都是在考虑所有后续可能性的基础上得出的,从而保证了计算结果的准确性。

相关问题