算法每日练习高频常考「位运算」题目总结
Posted 在路上的德尔菲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法每日练习高频常考「位运算」题目总结相关的知识,希望对你有一定的参考价值。
题目一:只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
输入: [2,2,1]
输出: 1
输入: [4,1,2,1,2]
输出: 4
题解一
排序后将相同大小值会放在一起,如果相邻两个值不相等即为只出现一次的数字。
public static int getOnceNumber(int[] nums) {
Arrays.sort(nums);
int i = 0;
for (; i < nums.length - 1; i++) {
if (nums[i] == nums[i + 1]) {
i++;
continue;
}
break;
}
return nums[i];
}
- 时间复杂度:O(logN)
- 空间复杂度:O(1)
题解二
使用HashSet,空间复杂度提高,有优化空间
public static int getOnceNumber(int[] nums) {
HashSet<Integer> set = new HashSet<>();
for (int num : nums) {
if (set.contains(num)) {
set.remove(num);
} else {
set.add(num);
}
}
return set.iterator().next();
}
- 时间复杂度:O(N)
- 空间复杂度:O(N)
解题三
相同的数字相异或会为0,遍历异或所有元素,最后得到的结果为只出现一次的数字
public static int getOnceNumber(int[] input) {
int length = input.length;
int res = 0;
for (int i = 0; i < length; i++) {
res = input[i] ^ res;
}
return res;
}
- 时间复杂度:O(N)
- 空间复杂度:O(1)
其他方法如先排序再遍历时间复杂度为O(nlogN),然后再遍历;使用HashMap存放各个元素,如果表中存在则删除,最后哈希表中仅剩的元素即为只出现一次的元素,时间复杂度为O(N),空间复杂度为O(N),都不够像位运算优美。
远景能源三面算法题
题目二:子集
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
运用位运算,举个栗子比较好理解,比如得到结果[2,3],如何向里层list需要添加2和3呢?3转化为二进制为011,各个位置上向右移动直到体现在个位,然后与1相与,如果为1说明原位置上为1,即需添加进里层list。
1 | 2 | 3 | 结果 |
---|---|---|---|
0 | 0 | 0 | [] |
0 | 0 | 1 | [3] |
0 | 1 | 0 | [2] |
0 | 1 | 1 | [2,3] |
1 | 0 | 0 | [1] |
1 | 0 | 1 | [1,3] |
1 | 1 | 0 | [1,2] |
1 | 1 | 1 | [1,2,3] |
public static List<List<Integer>> subsets(int[] nums) {
int size = nums.length;
//结果为2^size 也等于 1 << size
int n = 1 << size;
ArrayList<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < n; i++) {
ArrayList<Integer> cur = new ArrayList<>();
for (int j = 0; j < size; j++) {
if (((i >> j) & 1) == 1){
cur.add(nums[j]);
}
}
res.add(cur);
}
return res;
}
字节跳动二面算法题
题目三:2的幂
给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。
如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方。
输入:n = 16
输出:true
解释:24 = 16
输入:n = 5
输出:false
首先要明白如果n为负数,是不可能为2的幂的
其次n & (n-1) 表示可以将n二进制的最低位1移除
举个栗子🌰,4 二进制为 100,100 & 011 = 000,将4最低位的1移除后结果二进制中不再有1。
再举个栗子🌰,7二进制为111,111 & 110 = 110,将7最低位的1移除后结果二进制中还有两个1。
只要n & (n-1) > 0 说明n移除最低位的1后二进制中还有1,故n & (n-1) = 0说明n为2的幂,移除后二进制中不再有1。
public boolean isPowerOfTwo(int n) {
return n > 0 &&(n & (n-1)) == 0;
}
- 时间复杂度:O(N)
- 空间复杂度:O(1)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/power-of-two
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目四:比特位计数
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
输入: 5
输出: [0,1,1,2,1,2]
public int[] countBits(int n) {
int[] res = new int[n + 1];
for (int i = 0; i <= n; i++) {
res[i] = getBitCount(i);
}
return res;
}
/**
* Brian Kernighan算法
* 对于任意整数x 令 x = x & (x-1),
* 该运算将x的二进制表示的最后的一个1变成0,对x重复该操作,直到x变成0
* */
public int getBitCount(int pos) {
int count = 0;
while (pos > 0) {
pos &= (pos - 1);
count++;
}
return count;
}
- 时间复杂度:O(N)
- 空间复杂度:O(1)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/counting-bits
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目五:丢失的数字
给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。
解题一
排序后遍历,如果两个数之间相差不为1则为中间丢失的数
- 时间复杂度:O(NlogN)
- 空间复杂度:O(1)
解题二
由于[0,n]是等差数列,可以求0~n所有元素的和,用公式n*n/2,注意区分n为奇数和偶数的情况,然后减去数组中元素,剩余的数即为丢失的数
题解三
存在的数与位置相与,终究会是0,剩下的结果即为丢失的数,其中注意起始先得到数组的长度
举个栗子🌰[3,0,1]
3 ^ (0 ^ 3) ^ (1 ^ 0) ^ (2 ^ 1) = 2
public int missingNumber(int[] nums) {
int res = nums.length;
for (int i = 0; i < nums.length; i++) {
res ^= i ^ nums[i];
}
return res;
}
- 时间复杂度:O(N)
- 空间复杂度:O(1)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/missing-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
小红书一面
以上是关于算法每日练习高频常考「位运算」题目总结的主要内容,如果未能解决你的问题,请参考以下文章