We have an array `A` of non-negative integers.
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]
.
Return the number of possible results. (Results that occur more than once are only counted once in the final answer.)
Example 1:
Input: [0]
Output: 1
Explanation:
There is only one possible result: 0.
Example 2:
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:
Input: [1,2,4]
Output: 6
Explanation:
The possible results are 1, 2, 3, 4, 6, and 7.
Note:
1 <= A.length <= 50000
0 <= A[i] <= 10^9
這是一道蠻有意思的題目,說是給了我們一個數組,里面都是非負數,問我們所有連續的子數組'或'起來能產生多少個不同的值。雖說這只是一道 Medium 的題,但是直覺告訴博主,暴力遍歷所有子數組,並且一個一個的'或'將會產生大量的重復運算,不出意外應該是會 TLE 的。所以博主的第一直覺是能不能建立類似累加和一樣的數組,然后快速計算任意區間的總'或'值,嘗試了一下,雖然可以建立累加'或'數組,但是無法得到正確的區間總'或'值,博主甚至嘗試了'異或',仍然不對,只得作罷。其實這道題的正確解法還是蠻巧妙的,感覺不容易一下子想到,這里主要參考了 [網上大神 zhoubowei 的帖子](https://leetcode.com/problems/bitwise-ors-of-subarrays/discuss/165859/C%2B%2B-O(kN)-solution),舉個例子吧,比如數組 [0, 3, 4, 6, 5],寫成二進制的就是 [001, 011, 100, 110, 101],生成子數組的方法跟生成子集合 [Subsets](http://www.cnblogs.com/grandyang/p/4309345.html) 有些類似,但由於子數組必須是連續的,所以個數比子集合要少一些,生成的方法也是在現有的集合都加入當前數字,並每次新加一個只有當前數字的集合,順序如下:
[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個不同的集合,代表了所有的子數組,我們對每個集合都計算總'或'值,可以得到:
001
011 011
111 111 100
111 111 110 110
111 111 111 111 101
之前提到了,若對於每個集合都一個一個的'或'起來,將會十分的不高效,而其實這里面可能會有許多重復值,所以對重復值只需要保留一個,實際上就可以變成:
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 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)