我有一个我在网上找到的程序,它基本上告诉String
是否包含所有唯一字符,下面是代码
private static boolean areCharsUnique(String str) {
if (str.length() > 256)
return false;
int checker = 0;
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i) - 'a';
if ((checker & (1 << val)) > 0) {
return false;
}
checker |= (1 << val);
}
return true;
}
我对这行代码if ((checker & (1 << val)) > 0)
以及
checker |= (1 << val);
我知道<<
是一个左移操作员,但在上述情况下左移的确切程度如何?
简而言之,上述计划如何运作?
答案 0 :(得分:7)
此代码的工作原理是ASCII字符集在其映射中具有连续字符,以便a == 97, b == 98
,等等。
从此开始,您可以计算a
字符的增量距离,例如'e' - 'a' = 5
。该距离用于设置(通过checker |= (1 << val)
)整数(具有32位)的位。
因此,如果找到'e'
字符,则checker
将索引5处的位设置为1。
通过确保您从未找到之前已设置的位(通过if (checker & (1 << val)) > 0)
),可以对每个字符进行此操作。
这仅适用于小写字符(即使因为int有32位)。 HashSet<Character>
肯定会更好。
答案 1 :(得分:2)
每个字符都转换为从0(=='a')到26(=='z')及更高的数字索引。对于每个索引,设置整数值(=='checker')中的相应位。如果已设置该索引的位,则可以确定该字符已包含在给定字符串中。
请注意,此算法仅适用于小写字符串,对于大写字符,该值将溢出并提供不可靠的结果。一个解决方法是将'checker'类型从int转换为long。
答案 2 :(得分:1)
此代码将每个小写字符的存在存储为32位整数中的单个位。
1 << val
仅使用该位设置计算数字。
答案 3 :(得分:1)
我们将每个字符转换为从0('a')到25('z')的数字索引
int val = str.charAt(i) - 'a';
这里我们看一下checker
的二进制表示
例如,如果checker = 001
这意味着我们已经计算了char'a',因为第一位设置为1。
在这一行中,我们检查是否设置了与当前字母相关的位。 1<<val
代表00100..00
,其中1
位于val
- 左侧的位置。其他数字为零。关于二进制操作,您可以阅读at TopCoder
if ((checker & (1 << val)) > 0) {...}
这一行checker |= (1 << val);
在位置val
处将位从左侧设置为1
中的checker
。
修改强>
在这里,您可以假设checker
,如bool arr[32]
,
和
int val = str.charAt(i) - 'a';
与if(arr[str.charAt(i) - 'a'] == true) ...
和
checker |= (1 << val);
等于arr[val] = true
。
因此,在请求时,您将arr
的所有元素设置为零。
val
- 是从'a'到'z'的字母的整数表示。