什么是按位运算?
按位运算是指直接对整数二进制位进行操作的运算。按位运算符对整数的二进制位的每一位进行逐一处理而不是对整数整体进行的数值进行处理。
常见的按位运算符包括:
按位与(AND)&:当两个对应的二进制位都为1时,结果为1,否则为0。
5 & 3 //二进制:0101 & 0011 -> 0001 结果:1
按位或(OR)|:当两个对应的二进制位中,有一个为1时,结果为1,否则为0。
5 | 3 //二进制:0101 | 0011 -> 0111 结果:7
按位异或(XOR)^:当两个对应的二进制位不同时,结果为1,否则为0。
5 ^ 3 //二进制:0101 ^ 0011 -> 0110 结果:6
按位取反(NOT)~:将一个整数的每一个二进制位取反(0变1,1变0),注意取反操作可能会导致符号位发生变化,因此结果可能为负数。
~5 //二进制:0101 -> 1010(取反结果取决于机器的位数)
左移(Left Shift)<<:将一个数的二进制位向左移动指定的位数,右边用0填充。移动n位相当于乘以。
5 << 1 //二进制:0101 -> 1010 结果:10
右移(Right Shift)>>:将一个数的二进制位向右移动指定的位数。对于有符号数,右移时,左边用符号位填充;对于无符号数,左边用 0 填充。
5 >> 1 //二进制:0101 -> 0010 结果:2
什么是逻辑运算?
逻辑运算符用于对布尔表达式(true或false)进行逻辑操作。
常见的逻辑运算符有:
逻辑与(AND)&&:当两个布尔表达式都为true时,结果为true,否则为false。
true && false // 结果: false
逻辑或 (OR) || : 当两个布尔表达式中有一个为 true 时,结果为 true。
true || false // 结果: true
逻辑非 (NOT) ! : 取布尔表达式的相反值。
!true // 结果: false
总结
寻找独特数字卡片例题
问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求:
- 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
- 尽量减少额外空间的使用,以体现你的算法优化能力。
测试样例
样例1:
输入:
cards = [1, 1, 2, 2, 3, 3, 4, 5, 5]
输出:4
解释:拿到数字 4 的同学是唯一一个没有配对的。
样例2:
输入:
cards = [0, 1, 0, 1, 2]
输出:2
解释:数字 2 只出现一次,是独特的卡片。
样例3:
输入:
cards = [7, 3, 3, 7, 10]
输出:10
解释:10 是班级中唯一一个不重复的数字卡片。
约束条件
- 1 ≤ cards.length ≤ 1001
- 0 ≤ cards[i] ≤ 1000
- 班级人数为奇数
- 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次
解题思路
-
理解问题:数组中除了一个数字外,其他数字都出现了两次。我们需要找到这个唯一的数字。
-
数据结构选择:由于题目要求时间复杂度为 O(n),我们可以考虑使用位运算来解决这个问题。具体来说,使用异或运算(XOR)可以很好地解决这个问题。
-
算法步骤:
- 初始化一个变量
result为 0。 - 遍历数组中的每一个元素,将
result与当前元素进行异或运算。 - 由于异或运算的性质(
a ^ a = 0和a ^ 0 = a),所有出现两次的数字会相互抵消,最终result中剩下的就是唯一出现一次的数字。
- 初始化一个变量
答案示例
public class Main {
public static int solution(int[] cards) {
// Edit your code here
int result=0;
for(int card:cards){
result^=card;
}
return result;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) );
System.out.println(solution(new int[]{0, 1, 0, 1, 2}) );
}
}
就说到这里啦,再见!!!