【算法每日练习】高频常考「位运算」题目总结

题目一:只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
输入: [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。

123结果
000[]
001[3]
010[2]
011[2,3]
100[1]
101[1,3]
110[1,2]
111[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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

小红书一面

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值