首先照搬原题,
面试题 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