以下代码将检查字符串中是否有任何重复的字符,但我不理解if子句:
public static boolean isUniqueChars(String str) {
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;
}
Run Code Online (Sandbox Code Playgroud)
我试图查找一些引用,我是新移位,所有我理解的是<<左移或右移二进制数.你能解释一下checker | =(1 << val)是如何工作的吗?以及'if'陈述.
Arj*_* SK 17
我也正在阅读这本书Cracking the Code Interview,最后搜索了一个明确的解释.最后我理解了这个概念.
这是方法.
注意 :
我们将在下面的代码中假设字符串只是小写'a'到'z'.这将允许我们只使用一个int.
Java 整数大小为32
小写字母的数量是26
所以我们可以用十进制表示法在一个整数内清楚地设置0/1(真或假)值.
它类似于bool访问[32]. bool使用1个字节.因此,您需要32个字节来存储访问的bool [32].
位屏蔽是对此的空间优化.
开始吧 :
int val = str.charAt(i) - 'a';
对于'b',它是1.即66-65.
(1 << val) // 1<<1 => 10(binary)
现在让我们看看如何按位和工作
0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1
Run Code Online (Sandbox Code Playgroud)
所以通过以下代码:
(checker & (1 << val))
Run Code Online (Sandbox Code Playgroud)
我们检查checker [val] == 0.假设我们已经遇到'b'.
check = 0000 0000 0000 0000 0000 1000 1000 0010 &
'b' = 0000 0000 0000 0000 0000 0000 0000 0010
----------------------------------------------
result= 0000 0000 0000 0000 0000 0000 0000 0010
Run Code Online (Sandbox Code Playgroud)
即十进制值= 2,其> 0
所以你最后我们理解了这一部分.
if ((checker & (1 << val)) > 0)
return false;
Run Code Online (Sandbox Code Playgroud)
(这部分称为位掩码.)
或者是真相表
0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1
Run Code Online (Sandbox Code Playgroud)
所以
check = 0000 0000 0000 0000 0000 1000 1000 0000 |
'b' = 0000 0000 0000 0000 0000 0000 0000 0010
----------------------------------------------
result= 0000 0000 0000 0000 0000 1000 1000 0010
Run Code Online (Sandbox Code Playgroud)
这简化了这一部分:
checker |= (1 << val); // checker = checker | (1 << val);
Run Code Online (Sandbox Code Playgroud)
我希望这有助于某人!
好像我参加晚会晚了,但让我为解释解释一点点。
首先,AND即&运算:
0 & 0 = 0
1 & 0 = 0
0 & 1 = 0
1 & 1 = 1
Run Code Online (Sandbox Code Playgroud)
因此,基本上,如果给定一点,并且想知道它是1还是0,则将其与1匹配。如果结果为1,则您有1,否则您有0。我们将使用它&以下的属性。
OR即| 操作
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 1
Run Code Online (Sandbox Code Playgroud)
因此,基本上,如果给了您一点点,并且您想要对其做一些事情,以使输出始终为1,则可以执行| | | | | | | | | | | | |,它们,它们分别是:1。
现在,在Java中,类型int为4字节,即32位。因此,我们可以将int自身用作数据结构,以更简单的方式存储32个状态或布尔值,因为位可以是0或1,即false或true。由于我们假定字符串仅由小写字符组成,因此我们在int内有足够的空间来为26个字符中的每个字符存储一个布尔值!
因此,首先我们初始化我们的数据结构,checker将其调用为0,但只不过是32个零:0000000000000000000000。
到目前为止,一切都很好?
现在我们遍历字符串,对于每个字符,首先我们得到该字符的整数表示。
int val = str.charAt(i) - 'a';
Run Code Online (Sandbox Code Playgroud)
我们减去a它是因为我们希望我们的整数基于0。因此,如果vals:
a = 0 i.e. `0000000000000000000000`
b = 1 i.e. `0000000000000000000001`
c = 2 i.e. `0000000000000000000010`
d = 4 i.e. `0000000000000000000100`
Run Code Online (Sandbox Code Playgroud)
现在,如上所示,a是32个零,但是其余字符具有单个1和31个零。因此,当我们使用这些字符时,left shift每个字符都加1,即(1 << val),因此每个字符都有一个1位和31个零位:
a = 1 i.e. `0000000000000000000001`
b = 2 i.e. `0000000000000000000010`
c = 4 i.e. `0000000000000000000100`
d = 8 i.e. `0000000000000000001000`
Run Code Online (Sandbox Code Playgroud)
设置完成。现在我们做两件事:
首先假设所有字符都不同。对于我们遇到的每个字符,我们都希望我们的数据结构(即检查器)具有该字符的1。因此,我们使用上面描述的OR属性在我们的数据结构中生成1,因此我们这样做:
checker = checker | (1 << val);
Run Code Online (Sandbox Code Playgroud)因此,checker为遇到的每个字符存储1。
现在我们来讨论字符可以重复的部分。因此,在执行步骤1之前,我们要确保检查器在与当前字符对应的位置上已经没有1。所以我们检查
checker & (1 << val)
Run Code Online (Sandbox Code Playgroud)因此,借助上述AND属性,如果我们从此操作中获得1,则checker在该位置已经有1,这意味着我们之前必须已经遇到过此字符。因此我们立即返回false。
就是这样。如果所有&检查都返回0,则最终返回true,表示没有字符重新排列。
1 << val是相同的2 to the degree of val。所以它是
一个在其二进制表示中只有一个 1 的数字(val+1如果从
数字的右侧向左侧数,则该数字位于位置 )。
a |= b基本上意味着:从
二进制表示中设置a所有二进制标志/标志(并保留已设置的标志)。ba
| 归档时间: |
|
| 查看次数: |
4497 次 |
| 最近记录: |