[LeetCode] 898. Bitwise ORs of Subarrays 子数组按位或操做



We have an array A of non-negative integers.html

For every (contiguous) subarray B = [A[i], A[i+1], ..., A[j]] (with i <= j), we take the bitwise OR of all the elements in B, obtaining a result A[i] | A[i+1] | ... | A[j].git

Return the number of possible results.  (Results that occur more than once are only counted once in the final answer.)github

Example 1:数组

Input: [0]
Output: 1
Explanation:
There is only one possible result: 0.

Example 2:code

Input: [1,1,2]
Output: 3
Explanation:
The possible subarrays are [1], [1], [2], [1, 1], [1, 2], [1, 1, 2].
These yield the results 1, 1, 2, 1, 3, 3.
There are 3 unique values, so the answer is 3.

Example 3:htm

Input: [1,2,4]
Output: 6
Explanation:
The possible results are 1, 2, 3, 4, 6, and 7.

Note:blog

  1. 1 <= A.length <= 50000
  2. 0 <= A[i] <= 10^9



这是一道蛮有意思的题目,说是给了咱们一个数组,里面都是非负数,问咱们全部连续的子数组'或'起来能产生多少个不一样的值。虽然说这只是一道 Medium 的题,可是直觉告诉博主,暴力遍历全部子数组,而且一个一个的'或'将会产生大量的重复运算,不出意外应该是会 TLE 的。因此博主的第一直觉是能不能创建相似累加和同样的数组,而后快速计算任意区间的总'或'值,尝试了一下,虽然能够创建累加'或'数组,可是没法获得正确的区间总'或'值,博主甚至尝试了'异或',仍然不对,只得做罢。其实这道题的正确解法仍是蛮巧妙的,感受不容易一会儿想到,这里主要参考了 网上大神 zhoubowei 的帖子,举个例子吧,好比数组 [0, 3, 4, 6, 5],写成二进制的就是 [001, 011, 100, 110, 101],生成子数组的方法跟生成子集合 Subsets 有些相似,但因为子数组必须是连续的,因此个数比子集合要少一些,生成的方法也是在现有的集合都加入当前数字,并每次新加一个只有当前数字的集合,顺序以下:element

[001]
[001 011] [011]
[001 011 100] [011 100] [100]
[001 011 100 110] [011 100 110] [100 110] [110]
[001 011 100 110 101] [011 100 110 101] [100 110 101] [110 101] [101]

咱们能够看到,最开始就只有一个集合 [001],而后对于数字 011,先放到现有集合中,变成 [001 011],而后再新建一个本身的集合 [011],对于后面的数字都是一样的操做,最后咱们就有5个不一样的集合,表明了全部的子数组,咱们对每一个集合都计算总'或'值,能够获得:leetcode

001
011 011
111 111 100
111 111 110 110
111 111 111 111 101

以前提到了,若对于每一个集合都一个一个的'或'起来,将会十分的不高效,而其实这里面可能会有许多重复值,因此对重复值只须要保留一个,实际上就能够变成:get

001
011
111 100
111 110
111 101

这样数字就减小了不少,使得计算效率也就大大的提升了。具体的作法是,开始先创建两个 HashSet,分别是 res 和 cur,而后遍历数组A,对于每一个遍历到的数字,首先生成一个本身的集合 tmp,而后遍历集合 cur 中的全部数字,将当前数字和 cur 中的每一个数字相'或',并存入 tmp 中,因为 HashSet 能够自动去重复,因此 tmp 中保存的只有不一样的值,而后将 tmp 所有赋值给 cur,再将 cur 中的全部值加入结果 res 中,因为结果 res 也是 HashSet,也能够自动去重复,最后留在 res 中的就是全部不一样的子数组的总'或'值,参见代码以下:


class Solution {
public:
    int subarrayBitwiseORs(vector<int>& A) {
        unordered_set<int> res, cur;
        for (int i : A) {
            unordered_set<int> tmp = {i};
            for (int j : cur) tmp.insert(i | j);
            cur = tmp;
            for (int j : cur) res.insert(j);
        }
        return res.size();
    }
};



Github 同步地址:

https://github.com/grandyang/leetcode/issues/898



参考资料:

https://leetcode.com/problems/bitwise-ors-of-subarrays/

https://leetcode.com/problems/bitwise-ors-of-subarrays/discuss/165859/C%2B%2B-O(kN)-solution

https://leetcode.com/problems/bitwise-ors-of-subarrays/discuss/165881/C%2B%2BJavaPython-O(30N)



LeetCode All in One 题目讲解汇总(持续更新中...)

相关文章
相关标签/搜索