874. 模拟行走机器人
解题思路
使用hash+模拟就可以解决。
- 题目涉及东南西北四个在二维平面上的方向,我们就可以用四个二元组将这四个方向表示出来。东:
{1,0}
,南:{0,-1}
,西:{-1,0}
,北:{0,1}
,这四个方向按照顺时针方向存到数组中就是北东南西,这样我们就可以根据题目要求,右转数组下标就右移,左转就左移,细节处理就是西右转和北左转,可以使用%4
,也可以使用三目运算符。 - 然后就是遍历
commands
数组,-1
就右转,-2
就左转,否则就前进。但是前进方向有障碍物怎么办,这里我们使用hash
和pair
存储障碍物的位置,查找的时候比一个一个比较就快很多。我本来使用的是基于哈希表实现的unordered_set
,其查找速度是最快的,时间复杂度是0(1)
,可是他与pair
的组合会报错(不知道为什么)。所以就使用了相对较慢的set
。有关set
与unorder_set
的比较可以看下文的表格。 - 保存好之后,就可以开始模拟了,这里前进的时候,每前进一步就查找一次,找到了就说明过不去,这个方向就不能继续前进。位置就要回退到前一步的位置,所以代码实现的时候加了一定小细节。找不到就说明可行,然后记录并找最大的。遍历完
commands
之后就可以返回最终结果。
在c++中set
的底层实现以及优劣:
集合 | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
---|---|---|---|---|---|---|
std::set | 红黑树 | 有序 | 否 | 否 | O(logn) | O(logn) |
std::multiset | 红黑树 | 有序 | 是 | 否 | O(logn) | O(logn) |
std::unordered_set | 哈希表 | 无序 | 否 | 否 | O(1) | O(1) |
代码实现
class Solution {
public:
int robotSim(vector<int>& commands, vector<vector<int>>& obstacles)
{
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; //北东南西四个方向。
int k=0; //初始方向为北
int x=0,y=0; //当前机器人的坐标
int res=0; //记录最终结果
set<pair<int,int>>s; //使用set与pair来存障碍的位置
for(int i=0;i<obstacles.size();i++) //将障碍存到s中
{
s.insert(pair(obstacles[i][0],obstacles[i][1]));
}
for(int a:commands) //开始遍历
{
if(a==-1)k=k==3?0:k+1; //右转,k后移
else if(a==-2)k=k==0?3:k-1; //左转,k前移
else
{
for(int i=0;i<a;i++)
{
if(s.find(pair(x+dir[k][0],y+dir[k][1]))!=s.end()) //没有障碍就走下去,有就直接跳出循环,停止在这个方向继续前进
break;
x+=dir[k][0];
y+=dir[k][1];
res=max(res,x*x+y*y);
}
}
}
return res;
}
};