diff --git a/solution/0800-0899/0874.Walking Robot Simulation/README.md b/solution/0800-0899/0874.Walking Robot Simulation/README.md index e200e3327750b..1c6e678b8c30e 100644 --- a/solution/0800-0899/0874.Walking Robot Simulation/README.md +++ b/solution/0800-0899/0874.Walking Robot Simulation/README.md @@ -84,7 +84,23 @@ -**方法一:模拟** +**方法一:哈希表 + 模拟** + +我们定义一个长度为 $5$ 的方向数组 $dirs=[0, 1, 0, -1, 0]$,数组中的相邻两个元素表示一个方向。即 $(dirs[0], dirs[1])$ 表示向北,而 $(dirs[1], dirs[2])$ 表示向东,以此类推。 + +我们使用一个哈希表 $s$ 来存储所有障碍物的坐标,这样我们就可以在 $O(1)$ 的时间内判断下一步是否会遇到障碍物。 + +我们使用两个变量 $x$ 和 $y$ 来表示机器人当前所在的坐标,初始时 $x = y = 0$。变量 $k$ 表示机器人当前的方向,答案变量 $ans$ 表示机器人距离原点的最大欧式距离的平方。 + +接下来,我们遍历数组 $commands$ 中的每个元素 $c$: + +- 如果 $c = -2$,表示机器人向左转 $90$ 度,即 $k = (k + 3) \bmod 4$; +- 如果 $c = -1$,表示机器人向右转 $90$ 度,即 $k = (k + 1) \bmod 4$; +- 否则,表示机器人向前移动 $c$ 个单位长度。我们将机器人当前的方向 $k$ 与方向数组 $dirs$ 结合,即可得到机器人在 $x$ 轴和 $y$ 轴上的增量。我们将 $c$ 个单位长度的增量分别累加到 $x$ 和 $y$ 上,并判断每次移动后的新坐标 $(x, y)$ 是否在障碍物的坐标中,如果不在,则更新答案 $ans$,否则停止模拟,进行下一条指令的模拟。 + +最后返回答案 $ans$ 即可。 + +时间复杂度 $O(C \times n + m)$,空间复杂度 $O(m)$。其中 $C$ 表示每次可以移动的最大步数,而 $n$ 和 $m$ 分别表示数组 $commands$ 和数组 $obstacles$ 的长度。 @@ -95,18 +111,18 @@ ```python class Solution: def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int: - dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]] + dirs = (0, 1, 0, -1, 0) s = {(x, y) for x, y in obstacles} - ans, p = 0, 1 + ans = k = 0 x = y = 0 - for v in commands: - if v == -2: - p = (p + 3) % 4 - elif v == -1: - p = (p + 1) % 4 + for c in commands: + if c == -2: + k = (k + 3) % 4 + elif c == -1: + k = (k + 1) % 4 else: - for _ in range(v): - nx, ny = x + dirs[p][0], y + dirs[p][1] + for _ in range(c): + nx, ny = x + dirs[k], y + dirs[k + 1] if (nx, ny) in s: break x, y = nx, ny @@ -121,22 +137,22 @@ class Solution: ```java class Solution { public int robotSim(int[] commands, int[][] obstacles) { - int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; - Set s = new HashSet<>(); - for (int[] v : obstacles) { - s.add(v[0] + "." + v[1]); + int[] dirs = {0, 1, 0, -1, 0}; + Set s = new HashSet<>(obstacles.length); + for (var e : obstacles) { + s.add(f(e[0], e[1])); } - int ans = 0, p = 1; + int ans = 0, k = 0; int x = 0, y = 0; - for (int v : commands) { - if (v == -2) { - p = (p + 3) % 4; - } else if (v == -1) { - p = (p + 1) % 4; + for (int c : commands) { + if (c == -2) { + k = (k + 3) % 4; + } else if (c == -1) { + k = (k + 1) % 4; } else { - while (v-- > 0) { - int nx = x + dirs[p][0], ny = y + dirs[p][1]; - if (s.contains(nx + "." + ny)) { + while (c-- > 0) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (s.contains(f(nx, ny))) { break; } x = nx; @@ -147,6 +163,10 @@ class Solution { } return ans; } + + private int f(int x, int y) { + return x * 60010 + y; + } } ``` @@ -156,20 +176,27 @@ class Solution { class Solution { public: int robotSim(vector& commands, vector>& obstacles) { - vector> dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; - unordered_set s; - for (auto v : obstacles) s.insert(to_string(v[0]) + "." + to_string(v[1])); - int ans = 0, p = 1; + int dirs[5] = {0, 1, 0, -1, 0}; + auto f = [](int x, int y) { + return x * 60010 + y; + }; + unordered_set s; + for (auto& e : obstacles) { + s.insert(f(e[0], e[1])); + } + int ans = 0, k = 0; int x = 0, y = 0; - for (int v : commands) { - if (v == -2) - p = (p + 3) % 4; - else if (v == -1) - p = (p + 1) % 4; - else { - while (v--) { - int nx = x + dirs[p][0], ny = y + dirs[p][1]; - if (s.count(to_string(nx) + "." + to_string(ny))) break; + for (int c : commands) { + if (c == -2) { + k = (k + 3) % 4; + } else if (c == -1) { + k = (k + 1) % 4; + } else { + while (c--) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (s.count(f(nx, ny))) { + break; + } x = nx; y = ny; ans = max(ans, x * x + y * y); @@ -184,33 +211,28 @@ public: ### **Go** ```go -func robotSim(commands []int, obstacles [][]int) int { - dirs := [][]int{{-1, 0}, {0, 1}, {1, 0}, {0, -1}} - s := map[string]bool{} - for _, v := range obstacles { - t := strconv.Itoa(v[0]) + "." + strconv.Itoa(v[1]) - s[t] = true +func robotSim(commands []int, obstacles [][]int) (ans int) { + dirs := [5]int{0, 1, 0, -1, 0} + type pair struct{ x, y int } + s := map[pair]bool{} + for _, e := range obstacles { + s[pair{e[0], e[1]}] = true } - ans, p := 0, 1 - x, y := 0, 0 - for _, v := range commands { - if v == -2 { - p = (p + 3) % 4 - } else if v == -1 { - p = (p + 1) % 4 + var x, y, k int + for _, c := range commands { + if c == -2 { + k = (k + 3) % 4 + } else if c == -1 { + k = (k + 1) % 4 } else { - for i := 0; i < v; i++ { - nx, ny := x+dirs[p][0], y+dirs[p][1] - t := strconv.Itoa(nx) + "." + strconv.Itoa(ny) - if s[t] { - break - } - x, y = nx, ny + for ; c > 0 && !s[pair{x + dirs[k], y + dirs[k+1]}]; c-- { + x += dirs[k] + y += dirs[k+1] ans = max(ans, x*x+y*y) } } } - return ans + return } func max(a, b int) int { @@ -221,6 +243,37 @@ func max(a, b int) int { } ``` +### **TypeScript** + +```ts +function robotSim(commands: number[], obstacles: number[][]): number { + const dirs = [0, 1, 0, -1, 0]; + const s: Set = new Set(); + const f = (x: number, y: number) => x * 60010 + y; + for (const [x, y] of obstacles) { + s.add(f(x, y)); + } + let [ans, x, y, k] = [0, 0, 0, 0]; + for (let c of commands) { + if (c === -2) { + k = (k + 3) % 4; + } else if (c === -1) { + k = (k + 1) % 4; + } else { + while (c-- > 0) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (s.has(f(nx, ny))) { + break; + } + [x, y] = [nx, ny]; + ans = Math.max(ans, x * x + y * y); + } + } + } + return ans; +} +``` + ### **...** ``` diff --git a/solution/0800-0899/0874.Walking Robot Simulation/README_EN.md b/solution/0800-0899/0874.Walking Robot Simulation/README_EN.md index 8fbaa977aab15..5fe3cb052cd7d 100644 --- a/solution/0800-0899/0874.Walking Robot Simulation/README_EN.md +++ b/solution/0800-0899/0874.Walking Robot Simulation/README_EN.md @@ -78,6 +78,24 @@ The furthest point the robot ever gets from the origin is (0, 6), which squared ## Solutions +**Solution 1: Hash table + simulation** + +We define a direction array $dirs=[0, 1, 0, -1, 0]$ of length $5$, where adjacent elements in the array represent a direction. That is, $(dirs[0], dirs[1])$ represents north, and $(dirs[1], dirs[2])$ represents east, and so on. + +We use a hash table $s$ to store the coordinates of all obstacles, so that we can determine in $O(1)$ time whether the next step will encounter an obstacle. + +We use two variables $x$ and $y$ to represent the current coordinates of the robot, initially $x = y = 0$. The variable $k$ represents the current direction of the robot, and the answer variable $ans$ represents the maximum Euclidean distance squared of the robot from the origin. + +Next, we traverse each element $c$ in the array $commands$: + +- If $c = -2$, it means that the robot turns left by $90$ degrees, that is, $k = (k + 3) \bmod 4$; +- If $c = -1$, it means that the robot turns right by $90$ degrees, that is, $k = (k + 1) \bmod 4$; +- Otherwise, it means that the robot moves forward by $c$ units of length. We combine the robot's current direction $k$ with the direction array $dirs$, and we can get the increment of the robot on the $x$ axis and the $y$ axis. We add the increment of $c$ units of length to $x$ and $y$ respectively, and judge whether the new coordinates $(x, y)$ after each move are in the coordinates of obstacles. If not, update the answer $ans$, otherwise stop simulating and perform the simulation of the next instruction. + +Finally return the answer $ans$. + +Time complexity is $O(C \times n + m)$, space complexity is $O(m)$. Where $C$ represents the maximum number of steps that can be moved each time, and $n$ and $m$ respectively represent the lengths of arrays $commands$ and arrays $obstacles$. + ### **Python3** @@ -85,18 +103,18 @@ The furthest point the robot ever gets from the origin is (0, 6), which squared ```python class Solution: def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int: - dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]] + dirs = (0, 1, 0, -1, 0) s = {(x, y) for x, y in obstacles} - ans, p = 0, 1 + ans = k = 0 x = y = 0 - for v in commands: - if v == -2: - p = (p + 3) % 4 - elif v == -1: - p = (p + 1) % 4 + for c in commands: + if c == -2: + k = (k + 3) % 4 + elif c == -1: + k = (k + 1) % 4 else: - for _ in range(v): - nx, ny = x + dirs[p][0], y + dirs[p][1] + for _ in range(c): + nx, ny = x + dirs[k], y + dirs[k + 1] if (nx, ny) in s: break x, y = nx, ny @@ -109,22 +127,22 @@ class Solution: ```java class Solution { public int robotSim(int[] commands, int[][] obstacles) { - int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; - Set s = new HashSet<>(); - for (int[] v : obstacles) { - s.add(v[0] + "." + v[1]); + int[] dirs = {0, 1, 0, -1, 0}; + Set s = new HashSet<>(obstacles.length); + for (var e : obstacles) { + s.add(f(e[0], e[1])); } - int ans = 0, p = 1; + int ans = 0, k = 0; int x = 0, y = 0; - for (int v : commands) { - if (v == -2) { - p = (p + 3) % 4; - } else if (v == -1) { - p = (p + 1) % 4; + for (int c : commands) { + if (c == -2) { + k = (k + 3) % 4; + } else if (c == -1) { + k = (k + 1) % 4; } else { - while (v-- > 0) { - int nx = x + dirs[p][0], ny = y + dirs[p][1]; - if (s.contains(nx + "." + ny)) { + while (c-- > 0) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (s.contains(f(nx, ny))) { break; } x = nx; @@ -135,6 +153,10 @@ class Solution { } return ans; } + + private int f(int x, int y) { + return x * 60010 + y; + } } ``` @@ -144,20 +166,27 @@ class Solution { class Solution { public: int robotSim(vector& commands, vector>& obstacles) { - vector> dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; - unordered_set s; - for (auto v : obstacles) s.insert(to_string(v[0]) + "." + to_string(v[1])); - int ans = 0, p = 1; + int dirs[5] = {0, 1, 0, -1, 0}; + auto f = [](int x, int y) { + return x * 60010 + y; + }; + unordered_set s; + for (auto& e : obstacles) { + s.insert(f(e[0], e[1])); + } + int ans = 0, k = 0; int x = 0, y = 0; - for (int v : commands) { - if (v == -2) - p = (p + 3) % 4; - else if (v == -1) - p = (p + 1) % 4; - else { - while (v--) { - int nx = x + dirs[p][0], ny = y + dirs[p][1]; - if (s.count(to_string(nx) + "." + to_string(ny))) break; + for (int c : commands) { + if (c == -2) { + k = (k + 3) % 4; + } else if (c == -1) { + k = (k + 1) % 4; + } else { + while (c--) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (s.count(f(nx, ny))) { + break; + } x = nx; y = ny; ans = max(ans, x * x + y * y); @@ -172,33 +201,28 @@ public: ### **Go** ```go -func robotSim(commands []int, obstacles [][]int) int { - dirs := [][]int{{-1, 0}, {0, 1}, {1, 0}, {0, -1}} - s := map[string]bool{} - for _, v := range obstacles { - t := strconv.Itoa(v[0]) + "." + strconv.Itoa(v[1]) - s[t] = true +func robotSim(commands []int, obstacles [][]int) (ans int) { + dirs := [5]int{0, 1, 0, -1, 0} + type pair struct{ x, y int } + s := map[pair]bool{} + for _, e := range obstacles { + s[pair{e[0], e[1]}] = true } - ans, p := 0, 1 - x, y := 0, 0 - for _, v := range commands { - if v == -2 { - p = (p + 3) % 4 - } else if v == -1 { - p = (p + 1) % 4 + var x, y, k int + for _, c := range commands { + if c == -2 { + k = (k + 3) % 4 + } else if c == -1 { + k = (k + 1) % 4 } else { - for i := 0; i < v; i++ { - nx, ny := x+dirs[p][0], y+dirs[p][1] - t := strconv.Itoa(nx) + "." + strconv.Itoa(ny) - if s[t] { - break - } - x, y = nx, ny + for ; c > 0 && !s[pair{x + dirs[k], y + dirs[k+1]}]; c-- { + x += dirs[k] + y += dirs[k+1] ans = max(ans, x*x+y*y) } } } - return ans + return } func max(a, b int) int { @@ -209,6 +233,37 @@ func max(a, b int) int { } ``` +### **TypeScript** + +```ts +function robotSim(commands: number[], obstacles: number[][]): number { + const dirs = [0, 1, 0, -1, 0]; + const s: Set = new Set(); + const f = (x: number, y: number) => x * 60010 + y; + for (const [x, y] of obstacles) { + s.add(f(x, y)); + } + let [ans, x, y, k] = [0, 0, 0, 0]; + for (let c of commands) { + if (c === -2) { + k = (k + 3) % 4; + } else if (c === -1) { + k = (k + 1) % 4; + } else { + while (c-- > 0) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (s.has(f(nx, ny))) { + break; + } + [x, y] = [nx, ny]; + ans = Math.max(ans, x * x + y * y); + } + } + } + return ans; +} +``` + ### **...** ``` diff --git a/solution/0800-0899/0874.Walking Robot Simulation/Solution.cpp b/solution/0800-0899/0874.Walking Robot Simulation/Solution.cpp index a92e06e8d4105..69ddd9394189e 100644 --- a/solution/0800-0899/0874.Walking Robot Simulation/Solution.cpp +++ b/solution/0800-0899/0874.Walking Robot Simulation/Solution.cpp @@ -1,26 +1,33 @@ -class Solution { -public: - int robotSim(vector& commands, vector>& obstacles) { - vector> dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; - unordered_set s; - for (auto v : obstacles) s.insert(to_string(v[0]) + "." + to_string(v[1])); - int ans = 0, p = 1; - int x = 0, y = 0; - for (int v : commands) { - if (v == -2) - p = (p + 3) % 4; - else if (v == -1) - p = (p + 1) % 4; - else { - while (v--) { - int nx = x + dirs[p][0], ny = y + dirs[p][1]; - if (s.count(to_string(nx) + "." + to_string(ny))) break; - x = nx; - y = ny; - ans = max(ans, x * x + y * y); - } - } - } - return ans; - } +class Solution { +public: + int robotSim(vector& commands, vector>& obstacles) { + int dirs[5] = {0, 1, 0, -1, 0}; + auto f = [](int x, int y) { + return x * 60010 + y; + }; + unordered_set s; + for (auto& e : obstacles) { + s.insert(f(e[0], e[1])); + } + int ans = 0, k = 0; + int x = 0, y = 0; + for (int c : commands) { + if (c == -2) { + k = (k + 3) % 4; + } else if (c == -1) { + k = (k + 1) % 4; + } else { + while (c--) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (s.count(f(nx, ny))) { + break; + } + x = nx; + y = ny; + ans = max(ans, x * x + y * y); + } + } + } + return ans; + } }; \ No newline at end of file diff --git a/solution/0800-0899/0874.Walking Robot Simulation/Solution.go b/solution/0800-0899/0874.Walking Robot Simulation/Solution.go index 7aa634ca12be9..85db9a5dc6888 100644 --- a/solution/0800-0899/0874.Walking Robot Simulation/Solution.go +++ b/solution/0800-0899/0874.Walking Robot Simulation/Solution.go @@ -1,30 +1,25 @@ -func robotSim(commands []int, obstacles [][]int) int { - dirs := [][]int{{-1, 0}, {0, 1}, {1, 0}, {0, -1}} - s := map[string]bool{} - for _, v := range obstacles { - t := strconv.Itoa(v[0]) + "." + strconv.Itoa(v[1]) - s[t] = true +func robotSim(commands []int, obstacles [][]int) (ans int) { + dirs := [5]int{0, 1, 0, -1, 0} + type pair struct{ x, y int } + s := map[pair]bool{} + for _, e := range obstacles { + s[pair{e[0], e[1]}] = true } - ans, p := 0, 1 - x, y := 0, 0 - for _, v := range commands { - if v == -2 { - p = (p + 3) % 4 - } else if v == -1 { - p = (p + 1) % 4 + var x, y, k int + for _, c := range commands { + if c == -2 { + k = (k + 3) % 4 + } else if c == -1 { + k = (k + 1) % 4 } else { - for i := 0; i < v; i++ { - nx, ny := x+dirs[p][0], y+dirs[p][1] - t := strconv.Itoa(nx) + "." + strconv.Itoa(ny) - if s[t] { - break - } - x, y = nx, ny + for ; c > 0 && !s[pair{x + dirs[k], y + dirs[k+1]}]; c-- { + x += dirs[k] + y += dirs[k+1] ans = max(ans, x*x+y*y) } } } - return ans + return } func max(a, b int) int { diff --git a/solution/0800-0899/0874.Walking Robot Simulation/Solution.java b/solution/0800-0899/0874.Walking Robot Simulation/Solution.java index 6f369af413b4a..15379ccd15d85 100644 --- a/solution/0800-0899/0874.Walking Robot Simulation/Solution.java +++ b/solution/0800-0899/0874.Walking Robot Simulation/Solution.java @@ -1,29 +1,33 @@ -class Solution { - public int robotSim(int[] commands, int[][] obstacles) { - int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; - Set s = new HashSet<>(); - for (int[] v : obstacles) { - s.add(v[0] + "." + v[1]); - } - int ans = 0, p = 1; - int x = 0, y = 0; - for (int v : commands) { - if (v == -2) { - p = (p + 3) % 4; - } else if (v == -1) { - p = (p + 1) % 4; - } else { - while (v-- > 0) { - int nx = x + dirs[p][0], ny = y + dirs[p][1]; - if (s.contains(nx + "." + ny)) { - break; - } - x = nx; - y = ny; - ans = Math.max(ans, x * x + y * y); - } - } - } - return ans; - } +class Solution { + public int robotSim(int[] commands, int[][] obstacles) { + int[] dirs = {0, 1, 0, -1, 0}; + Set s = new HashSet<>(obstacles.length); + for (var e : obstacles) { + s.add(f(e[0], e[1])); + } + int ans = 0, k = 0; + int x = 0, y = 0; + for (int c : commands) { + if (c == -2) { + k = (k + 3) % 4; + } else if (c == -1) { + k = (k + 1) % 4; + } else { + while (c-- > 0) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (s.contains(f(nx, ny))) { + break; + } + x = nx; + y = ny; + ans = Math.max(ans, x * x + y * y); + } + } + } + return ans; + } + + private int f(int x, int y) { + return x * 60010 + y; + } } \ No newline at end of file diff --git a/solution/0800-0899/0874.Walking Robot Simulation/Solution.py b/solution/0800-0899/0874.Walking Robot Simulation/Solution.py index 5772a069c2c15..e8e091ec93291 100644 --- a/solution/0800-0899/0874.Walking Robot Simulation/Solution.py +++ b/solution/0800-0899/0874.Walking Robot Simulation/Solution.py @@ -1,19 +1,19 @@ -class Solution: - def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int: - dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]] - s = {(x, y) for x, y in obstacles} - ans, p = 0, 1 - x = y = 0 - for v in commands: - if v == -2: - p = (p + 3) % 4 - elif v == -1: - p = (p + 1) % 4 - else: - for _ in range(v): - nx, ny = x + dirs[p][0], y + dirs[p][1] - if (nx, ny) in s: - break - x, y = nx, ny - ans = max(ans, x * x + y * y) - return ans +class Solution: + def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int: + dirs = (0, 1, 0, -1, 0) + s = {(x, y) for x, y in obstacles} + ans = k = 0 + x = y = 0 + for c in commands: + if c == -2: + k = (k + 3) % 4 + elif c == -1: + k = (k + 1) % 4 + else: + for _ in range(c): + nx, ny = x + dirs[k], y + dirs[k + 1] + if (nx, ny) in s: + break + x, y = nx, ny + ans = max(ans, x * x + y * y) + return ans diff --git a/solution/0800-0899/0874.Walking Robot Simulation/Solution.ts b/solution/0800-0899/0874.Walking Robot Simulation/Solution.ts new file mode 100644 index 0000000000000..6beceae7941d8 --- /dev/null +++ b/solution/0800-0899/0874.Walking Robot Simulation/Solution.ts @@ -0,0 +1,26 @@ +function robotSim(commands: number[], obstacles: number[][]): number { + const dirs = [0, 1, 0, -1, 0]; + const s: Set = new Set(); + const f = (x: number, y: number) => x * 60010 + y; + for (const [x, y] of obstacles) { + s.add(f(x, y)); + } + let [ans, x, y, k] = [0, 0, 0, 0]; + for (let c of commands) { + if (c === -2) { + k = (k + 3) % 4; + } else if (c === -1) { + k = (k + 1) % 4; + } else { + while (c-- > 0) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (s.has(f(nx, ny))) { + break; + } + [x, y] = [nx, ny]; + ans = Math.max(ans, x * x + y * y); + } + } + } + return ans; +}