我只是想学习按位/移位操作。
我遇到了以下程序,但是不理解AND条件部分(检查器&(1<<< val)在下面的程序中。什么时候最终值大于0?有人可以解释什么发生在那里?
示例输入: XYZZ
示例输出:
8388608Value 0checker 最终值
16777216Value 8388608checker 最终值
33554432Value 25165824checker 最终值
33554432Value 58720256checker 33554432最终值
public static boolean isUniqueChars(String str) {
int checker = 0;
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i) - 'a';
System.out.println((1 << val) + "Value");
System.out.println((checker) + "checker");
System.out.println(((checker & (1 << val))) + "final value\n");
if ((checker & (1 << val)) > 0) {
return false;
} else {
checker = checker | (1 << val);
}
}
return true;
}
}
答案 0 :(得分:6)
好的,只是为了确保你知道发生了什么:
int val = str.charAt(i) - 'a';
假设使用英文字母,这将取您(小写)字母的char值并减去97('a'的char值)以产生0到25之间的数字。不要对大写字符尝试此功能,除非在.toLowerCase()
.charAt(i)
,否则会出现错误
1 << val
向左移动1 val
个位置。例如,对于'x'(120 - 97 = 23,所以...... 1 << 23
),二进制表示将为00000000010000000000000000000000
好的,到目前为止和我在一起?
一开始,检查器全部为0位,因此它是00000000000000000000000000000000
所以...让我们输入数字而不是变量。对于我们的x
检查,checker & (1 << val)
变为00000000000000000000000000000000 & 00000000010000000000000000000000
等于00000000000000000000000000000000
,因为第23位未设置为检查器。
因此,处理x
后,我们将第23位添加到检查器并转到下一个字母:y
这一次,checker & (1 << val)
变为00000000010000000000000000000000 & 00000000100000000000000000000000
,等于{ {1}}因为第24位未在检查器中设置。
对于第一个00000000000000000000000000000000
,z
变为checker & (1 << val)
等于00000000110000000000000000000000 & 00000001000000000000000000000000
,因为第25位未在检查器中设置。
对于第二个00000000000000000000000000000000
,z
变为checker & (1 << val)
,等于00000001110000000000000000000000 & 00000001000000000000000000000000
(十进制33554432或2 ^ 25),因为第25位 设置在检查器中,00000001000000000000000000000000
现在为> 0
,函数返回true
。
答案 1 :(得分:1)
我认为你的功能是检查输入字符串中的所有字符是否不同。如果相同(小写)字符出现多次,则返回false。
checker
变量用作一种位图,用于累积到目前为止出现的字符。数据类型int
由32位组成,足以为每个字符分配一位(26)。
该函数循环遍历str的所有字符。行int val = str.charAt(i) - 'a';
根据字符('a'=&gt; 0,'b'=&gt; 1,'c'=&gt; 2等)为val
分配某种序数值。 )。
表达式1 << val
将(0..25)范围内的每个val分配给它的位位置。因此,字符'a'被映射到1&lt;&lt;&lt; 0 == 1 == 00000001,字符'd'被映射1&lt;&lt; 3 == 00001000,依此类推。每个字符都分配了唯一的位掩码,只有一位设置,所有其他位清零。
表达式(checker & (1 << val))
是&gt; 0如果在1 << val
中设置的位也设置在检查器中(请注意,检查器可能设置了多个位)。如果是这样,当前迭代的字符出现得更早,函数返回false。否则,当前字符的位掩码通过按位OR运算符|
添加到充当累加器的检查器。如果所有字符都已循环并且没有两次遇到任何字符,则该函数返回true。请注意,该函数可能会忽略大写和其他字符。