在leetcode刷题目的时候,遇到一个模拟机器人行走的问题(大家可以打开连接看看原题),题目内容如下图所示:
这个题目就是一个模拟的题目,本来以为能够简单AC的,但是出现问题。
我的题解思路: 就是储出好四个方向,接着把障碍物的位置存储到HashMap中,这样只需要模拟移动机器人一步一步移动就行,下一步不是障碍物就走,是障碍物就结束当前的直线移动。
出现了问题: 思路上没什么问题,但是我先用Java实现一下上述过程,我在思考障碍物的坐标是一个二维数组的形式给出来的,那我将每一组坐标存储到HashMap中的时候,这是对数组地址进行的Hash,不是依据内容进行Hash的,所以这样不能够实现判断下一步的坐标点是不是障碍物(原本计划就是每次移动之前,把下一步得坐标点拿到HashMap中存储的障碍物点中判断一下存在否,不存在就移动,存在的话就不能走)
于是很好奇官方题解是如何解决这个问题的,便看了参考题解:
Java题解
//Java实现方式
class Solution {
public int robotSim(int[] commands, int[][] obstacles) {
int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
int px = 0, py = 0, d = 1;
Set<Integer> set = new HashSet<Integer>();
for (int[] obstacle : obstacles) {
set.add(obstacle[0] * 60001 + obstacle[1]);
}
int res = 0;
for (int c : commands) {
if (c < 0) {
d += c == -1 ? 1 : -1;
d %= 4;
if (d < 0) {
d += 4;
}
} else {
for (int i = 0; i < c; i++) {
if (set.contains((px + dirs[d][0]) * 60001 + py + dirs[d][1])) {
break;
}
px += dirs[d][0];
py += dirs[d][1];
res = Math.max(res, px * px + py * py);
}
}
}
return res;
}
}
Python题解
# Python题解
class Solution:
def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int:
dirs = [[-1,0],[0,1],[1,0],[0,-1]]
px, py, d = 0, 0, 1
mp = set([tuple(i) for i in obstacles])
res = 0
for c in commands:
if c < 0: # 调整机器人方向
d += 1 if c== -1 else -1
d %= 4
else:
for i in range(c):
# 这里可以直接比较列表内容是否相等
if tuple([px + dirs[d][0], py + dirs[d][1]]) in mp:
break;
px, py = px + dirs[d][0], py + dirs[d][1]
res = max(res, px * px + py * py)
return res
我看了两个语言的实现方式,题目用的Set将障碍物的坐标存储,去了一次重(HashMap的key底层实现就是用Set,所以HashMap和Set都可以用来判断里面是否存在某一个元素),所以我开始题目就开始懵了,Java为啥不可以将数组传入Set,而为啥Python中就是直接把列表转化为元组,然后就可以作为Set了??
对于上面的困惑,我做了一些测试,把Python代码中的列表不转化为元组试一试,结果出现了下面的报错,原来Python中也不能将列表Hash化,那这样也就是说上面的问题不是语言差异带来的,而是编程设计不允许这样子。
顺着上面线索,我进行了一方探索,得到了下面的重要信息 大家可以看看原文:
上面报错说list是unhashable,那么就会有可哈希(hashable)类型。那么,什么类型为可哈希? 引用 Python3 官方解释:一个对象的哈希值如果在其生命周期内绝不改变,就被称为 可哈希 (它需要具有hash() 方法),并可以同其他对象进行比较(它需要具有eq() 方法)。可哈希对象必须具有相同的哈希值比较结果才会相同。一个对象的哈希值在生命周期内不改变,就被成为可哈希。 可哈希性使得对象能够作为字典键或集合成员使用,因为这些数据结构要在内部使用哈希值。可变容器(例如列表或字典)都不可哈希,只有可哈希对象才能作为字典的键。
而且在Python中对于tuple元素的hash化是通过元素内容来实现的,也就说在之后的题解中,我们可以将不变内容tuple化之后存储到set中,然后就可以便利的判断其他行来元素在不在set中了
今天遇见这个问题还是说明自己的基础不扎实,对于hash的原理过程了解的不够深刻,还需要多多加油,把基础知识打扎实了,这也会对未来的学习和工作很有帮助