LeetCode系列之位运算专题

1. 位运算题目概述

https://leetcode-cn.com/tag/bit-manipulation/

2. 典型题目

2.1 汉明距离

https://leetcode-cn.com/problems/hamming-distance/

int hammingDistance(int x, int y) {
    return hammingWeight(x ^ y);
}

运用下述题目的hanmmingWeight方法,很容易计算。

时间复杂度O(1),空间复杂度O(1)。

2.2 二进制链表转整数

https://leetcode-cn.com/problems/convert-binary-number-in-a-linked-list-to-integer/

2.3 多数元素

https://leetcode-cn.com/problems/majority-element/

2.4 位1的个数

https://leetcode-cn.com/problems/number-of-1-bits/

int hammingWeight(uint32_t n) {
    int count = 0;
    while (n) {
        n = n & (n - 1);
        count++;
    }
    return count;
}

这种算法有一个名字:布莱恩·克尼根算法

时间复杂度O(1),空间复杂度O(1)。

2.5 比特位计数

https://leetcode-cn.com/problems/counting-bits/

用到了成员变量,所以就把整个类定义都copy过来了

class Solution {
public:
    vector<int> countBits(int num) {
        if (num > index_) {
            fillBitsNumberVector(num);
        }
        return extractBitsNumberVector(num);
    }

private:
    int countNumberOf1(int n) {
        int count = 0;
        while (n) {
            n = n & (n - 1);
            count++;
        }
        return count;
    }

    void fillBitsNumberVector(int num) {
        for (int i = index_ + 1; i <= num; i++) {
            bitsNumberVec_.push_back(countNumberOf1(i));
        }
    }

    vector<int> extractBitsNumberVector(int num) {
        vector<int> ivec = bitsNumberVec_;
        ivec.resize(num + 1);
        return ivec;
    }

    vector<int> bitsNumberVec_;
    int index_ = -1;
};

经过试验发现,resize要比手动copy要快一些。

时间复杂度O(N),空间复杂度O(N)。

2.6 只出现一次的数字

https://leetcode-cn.com/problems/single-number/

条件最强的一个

int singleNumber(vector<int>& nums) {
    int ret = 0;
    for (int i : nums) {
        ret ^= i;
    }
    return ret;
}

时间复杂度O(N),空间复杂度O(1)。

https://leetcode-cn.com/problems/single-number-ii/

https://leetcode-cn.com/problems/single-number-iii/

2.7 2的幂

https://leetcode-cn.com/problems/power-of-two/

两个注意点

  • int64转一下,不然在输入INT_MIN时,会溢出
  • n == 0时,要额外处理
bool isPowerOfTwo(int n) {
    if (n == 0) return false;
    int64_t m = n;
    m = m & (m - 1);
    return m == 0;
}

时间复杂度O(1),空间复杂度O(1)。

2.8 数字的补数

https://leetcode-cn.com/problems/number-complement/

2.9 找不同

https://leetcode-cn.com/problems/find-the-difference/

思路和 2.7 一模一样,只是把异或运用到了char类型上,char类型本质上也是范围小一点的整型。所以,没毛病。

char findTheDifference(string s, string t) {
    char ret = 0;
    for (char c : s) {
        ret ^= c;
    }
    for (char c : t) {
        ret ^= c;
    }
    return ret;
}

时间复杂度O(N),空间复杂度O(1)。

2.10 两整数之和

https://leetcode-cn.com/problems/sum-of-two-integers/

int getSum(int a, int b) {
    while(b) {
        unsigned int carry = a & b;
        a = a ^ b;
        b = carry << 1;
    }

    return a;
}

carry一定要设置成unsigned int类型,否则会遇到“runtime error: left shift of 1073741824 by 1 places cannot be represented in type 'int'”的问题。

时间复杂度O(1),跟int的size有关;空间复杂度O(1)。

3. 总结

posted @ 2020-07-16 09:25  不写诗的诗人小安  阅读(945)  评论(0编辑  收藏  举报