这个Java代码如何确定String是否包含所有唯一字符?

时间:2013-01-14 19:10:59

标签: java operators

我有一个我在网上找到的程序,它基本上告诉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);

我知道<<是一个左移操作员,但在上述情况下左移的确切程度如何?

简而言之,上述计划如何运作?

4 个答案:

答案 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'的字母的整数表示。