我在尝试学习Python%的同时解决了样本问题......但是我得到的问题书在Java中存在问题和解决方案,所以我试图在两者之间来回转换语言。我刚刚学会了位移的工作方式,而且我一直在盯着这段代码试图找出第5行(和8)的确切内容......我试着写下一些例子,只是通过代码行按行,但由于某种原因,它对我来说仍然不是很明显...... 请有人澄清一下吗?
另外,根据我的理解,str.charAt(i)
返回一个角色对我来说真的很奇怪,然后你可以继续从另一个角色中减去它......就像申请{{} 1}}与Python中的int
相同的字符?
问题:实现一个算法来确定字符串是否具有所有唯一字符。
解决方案(仅限字符a-z):
ord()
答案 0 :(得分:3)
不确定。只有当str
中只包含小写字母时,此代码才真正有用。
checker
是一个32位整数,您使用32位中的26位来记录str
中特定字母的存在。因此,位0将用于记录a
的存在,位1将用于记录b
的存在,依此类推至位25,这将用于记录存在的z
。
基本算法是逐个字符地处理str
。对于每个字符,找到checker
中的相应位。如果已经设置,则该字符必须第二次出现 - 因此我们可以停止处理并返回false
。否则,设置该位。
如果到达字符串的末尾而没有找到任何重复的字符,则返回true
。
神奇之处在于以下步骤。
'a'
会将其转换为0到25之间的数字。<<
是“左移”运算符,它将位模式向左移动一些位。结果是1 << val
是特定位(1,2,4,8等)的位置值。 &
执行二进制AND,因此如果位checker & (1 << val)
被清除,则表达式val
将为0,如果已设置,则等于1 << val
。 |=
执行二进制OR,并将结果分配给左侧的变量。因此表达式checker |= (1 << val)
设置了位val
。答案 1 :(得分:2)
让我们尝试一个更简单的变化:
boolean isUniqueChars(String str) {
boolean[] seen = new boolean[26];
for (int i = 0; i < str.length(); i++) {
// convert char to 0-based offset
int index = str.charAt(i) - 'a';
if (seen[index]) {
// this char was seen already
return false;
}
seen[index] = true;
}
// no duplicates found
return true;
}
非常直率,对吧?我们创建一个布尔数组,使用字符偏移作为索引,并检查字符串中的每个字符,看看我们是否遇到过它。您发布的代码使用相同的逻辑,但改为使用更有效的位设置。
(1 << val)
将val
转换为位索引。 checker & (1 << val)
过滤掉其他索引,以便我们可以检查这一个。 (checker & (1 << val)) > 0
检查索引中是否有任何值。 checker |= (1 << val)
在索引处打开了位。所有其他逻辑都是相同的。
答案 2 :(得分:2)
首先,如果输入字符串包含字母“a”到“z”,则代码只能可靠地工作。
变量检查器是32位int。检查器中的每个位用作一个标志,表示存在26个字母'a'到'z'中的一个。
该行
int val = str.charAt(i) - 'a';
通过减去字符'a'的值,将存储在str索引i的字符转换为存储在val中的整数。是的,我认为pascal具有相同的Ord('')函数。
a = 0
b = 1
c = 2
etc
etc
etc
z = 25
代码
(1 << val)
将val移位到其位位置的适当值
所以
a = 0 = 1
b = 1 = 2
c = 2 = 4
d = 3 = 8
etc
etc
z = 25 = 33554432
if ((checker & (1 << val)) > 0)
确定该位是否已在检查器中设置,表示重复的字符。如果是,则该函数返回false。
否则
checker |= (1 << val)
通过二进制OR设置检查器中的位,然后再循环。