首先照搬原题,

面试题 01.01. 判定字符是否唯一

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false 

示例 2:

输入: s = "abc"
输出: true

限制:

  • 0 <= len(s) <= 100
  • 如果你不使用额外的数据结构,会很加分。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/is-unique-lcci

解法一 HashSet

因为这是一道简单题,按照一般的做法直接使用HashSet即可

class Solution {
    public boolean isUnique(String s) {
        Set<Character> set = new HashSet<>();
        char c;
        for (int i = 0;i<s.length();i++){
            c = s.charAt(i);
            if (set.contains(c)){
                return false;
            }
            set.add(c);
        }
        return true;
    }
}

解法二 位运算

同时,可以使用位运算的方式进行题目的解决,这里我使用一个int来存储对应位置字符的状态,如果为 1 则说明已经出现这个字符。

假如 int 有4位,每一位代表一个字符 分别为 a,b,c,d 那么字符串 ac 的表示即为 1010 ;

然后,新的字符使用1来表示,并用123减去 ASCII 码表对应位置字符所得到的数字作为要位移的距离。

最后使用与运算进行比对即可。

class Solution {
    public boolean isUnique(String s) {
        int ybits = 0; // 存放所有字符状态
        for (int i = 0;i<s.length();i++){
            char c = s.charAt(i);
            int db = 1;// 目标字符
            int ls = ybits; // 临时字符
            if ((ls>>(123-c) & db) == 1){ // 根据ASCII,把要比对的位置移动到最后一位,并与目标字符进行与运算,结果为1则说明字符重复。
                return false;
            }else {
                ybits+=db<<(123-c); //移动目标字符的位置并更新字符状态
            }
        }
        return true;
    }
}

Java 位运算(移位、位与、或、异或、非)

Java提供的位运算符有:左移( << )、右移( >> ) 、无符号右移( >>> ) 、位与( & ) 、位或( | )、位非( ~ )、位异或( ^ ),除了位非( ~ )是一元操作符外,其它的都是二元操作符。

1、左移( << )

Test1、将5左移2位:

package com.xcy;

public class Test {
    public static void main(String[] args) {
        System.out.println(5<<2);//运行结果是20
    }
}

运行结果是20,但是程序是怎样执行的呢?
首先会将5转为2进制表示形式(java中,整数默认就是int类型,也就是32位):

0000 0000 0000 0000 0000 0000 0000 0101 然后左移2位后,低位补0:

0000 0000 0000 0000 0000 0000 0001 0100 换算成10进制为20

2、右移( >> )

右移同理,只是和左移方向不一致

System.out.println(5>>2);//运行结果是1

还是先将5转为2进制表示形式:

0000 0000 0000 0000 0000 0000 0000 0101

然后右移2位,高位补0

0000 0000 0000 0000 0000 0000 0000 0001

3、无符号右移( >>> )

我们知道在Java中int类型占32位,可以表示一个正数,也可以表示一个负数。正数换算成二进制后的最高位为0,负数的二进制最高为为1

例如 -5换算成二进制后为:

1111 1111 1111 1111 1111 1111 1111 1011

我们分别对5进行右移3位、 -5进行右移3位和无符号右移3位:

public class Test {
    public static void main(String[] args) {
        System.out.println(5>>3);//结果是0
        System.out.println(-5>>3);//结果是-1
        System.out.println(-5>>>3);//结果是536870911
    }
}

我们来看看它的移位过程(可以通过其结果换算成二进制进行对比):

5换算成二进制:

0000 0000 0000 0000 0000 0000 0000 0101
5右移3位后结果为0,0的二进制为:

0000 0000 0000 0000 0000 0000 0000 0000 // (用0进行补位)

-5换算成二进制:

1111 1111 1111 1111 1111 1111 1111 1011
-5右移3位后结果为-1,-1的二进制为:

1111 1111 1111 1111 1111 1111 1111 1111 // (用1进行补位)
-5无符号右移3位后的结果 536870911 换算成二进制:

0001 1111 1111 1111 1111 1111 1111 1111 // (用0进行补位)

通过其结果转换成二进制后,我们可以发现,正数右移,高位用0补,负数右移,高位用1补,当负数使用无符号右移时,用0进行部位(自然而然的,就由负数变成了正数了)

注意:笔者在这里说的是右移,高位补位的情况。正数或者负数左移,低位都是用0补。(自行测试)

4、位与( & )

public class Test {
    public static void main(String[] args) {
        System.out.println(5 & 3);//结果为1
    }
}

还是老套路,将2个操作数和结果都转换为二进制进行比较:
5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101

3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011


1转换为二进制:0000 0000 0000 0000 0000 0000 0000 0001

位与:第一个操作数的的第n位于第二个操作数的第n位如果都是1,那么结果的第n为也为1,否则为0

5、位或( | )

public class Test {
    public static void main(String[] args) {
        System.out.println(5 | 3);//结果为7
    }
}

5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101

3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011


7转换为二进制:0000 0000 0000 0000 0000 0000 0000 0111
位或操作:第一个操作数的的第n位于第二个操作数的第n位 只要有一个是1,那么结果的第n为也为1,否则为0

6、位异或( ^ )

public class Test {
    public static void main(String[] args) {
        System.out.println(5 ^ 3);//结果为6
    }
}

5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101

3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011


6转换为二进制:0000 0000 0000 0000 0000 0000 0000 0110
位异或:第一个操作数的的第n位于第二个操作数的第n位 相反,那么结果的第n为也为1,否则为0

7、位非( ~ ) 位非是一元操作符

public class Test {
    public static void main(String[] args) {
        System.out.println(~5);//结果为-6
    }
}

5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101

-6转换为二进制:1111 1111 1111 1111 1111 1111 1111 1010

位非:操作数的第n位为1,那么结果的第n位为0,反之。

由位运算操作符衍生而来的有:

&=     按位与赋值
|=     按位或赋值
^=     按位非赋值
>>=    右移赋值
>>>=   无符号右移赋值
<<= 赋值左移

+=一个概念而已。

举个例子:

public class Test {
    public static void main(String[] args) {
        int a = 5
        a &= 3;
        System.out.println(a);//结果是1
    }
}

位运算内容转载来源链接:https://blog.csdn.net/xiaochunyong/article/details/7748713