我们有一个非负整数数组 A
。
对于每个(连续的)子数组 B = [A[i], A[i+1], ..., A[j]]
( i <= j
),我们对 B
中的每个元素进行按位或操作,获得结果 A[i] | A[i+1] | ... | A[j]
。
返回可能结果的数量。 (多次出现的结果在最终答案中仅计算一次。)
示例 1:
输入:[0]
输出:1
解释:
只有一个可能的结果 0 。
示例 2:
输入:[1,1,2]
输出:3
解释:
可能的子数组为 [1],[1],[2],[1, 1],[1, 2],[1, 1, 2]。
产生的结果为 1,1,2,1,3,3 。
有三个唯一值,所以答案是 3 。
示例 3:
输入:[1,2,4]
输出:6
解释:
可能的结果是 1,2,3,4,6,以及 7 。
提示:
1 <= A.length <= 50000
0 <= A[i] <= 10^9
本解答借鉴了https://blog.youkuaiyun.com/qq_20633793/article/details/82314599 这篇文章,若答主介意则给删除。
本文在对原文进行了部分补充:
解答思路如下:
class Solution {
public:
int subarrayBitwiseORs(vector<int>& A) {
//方法1,时间复杂度为O(n^2)
// int num=A.size();
// unordered_set<long> ans;
// for(int i=0;i<num;i++){
// long res=0;
// for(int j=1;j<=num-i;j++){
// res=A[i+j-1]|res;
// ans.insert(res);
// }
// }
// return ans.size();
//本题关键为去重,并选用Set的数据结构用来查找,去重
//假设输入为[1,4,2,8,16]
//这里的cur2 ,是动态规划的体现
unordered_set<int> res, cur, cur2;
//循环n次,
for (int i: A) {
cur2 = {i};
//i=8时,cur代表的是上一轮的cur2 ,为1|4|2, 4|2, 2 ,并利用set的特性将其中的冗余元素进行了去除
//最坏情况下,在第n圈中,循环n-1次
for (int j: cur) cur2.insert(i|j);
//处理后,cur2代表的是1|4|2|8, 4|2|8, 2|8, 8 并利用set的特性将其中的冗余元素进行了去除
cur = cur2;
for (int j: cur) res.insert(j); //对新结果进行了插入
}
return res.size();
}
};
如下图:
方法1采用,先排除当前位,如对于2,则从A到Z方向,每一个数都利用了上一"横"层的结果,在 纵向上体现了动态规划的思想,但这里无法进行优化,只能有多少行,就内层就循环多少次,而从8到0,这里也可以采用动态规划的思想,对于每个数,都可以利用上一"竖"列的结果,而这一竖列,每一格代表其本身及其右侧进行或运算累计结果,这一数列存在大量冗余的数据,采用Set的数据结构,去除了冗余,大大地降低了时间复杂度。