我们有一个非负整数数组 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
最有方法的思路:
中间那一列保存的是:第一个set保存的是到目前为止的或的结果,第二个set保存的是我前面的那个元素
然后见尽力啊新的元素的时候,我就用心的元素去或上这两个set,然后加上自己本身,就是结果。因为自己本身或就是自己本身
也是动态规划的思想。
显示以1结尾的,只有1
然后2进来,或上1 得3 并加上自己本身
这是一种空间换时间的做法,一个cur集合储存上一次循环的位或结果集合,将这些集合和当前循环的元素进行位或运算,在补充上当前元素。然后一个res和cur取并集。
为什么要有一个cur而不直接用res呢?或者为什么要用两个集合而不是一个集合呢?
考虑[1,2,4]这个测试用例:
第一轮循环时,a=1,cur={1},res={1}
第二轮循环时,a=2,cur = {1|2}|{2} = {2,3}, res={1,2,3}
第三轮循环时,a=4,cur={2|4, 3|4}|{4} = {4, 6, 7},res={1,2,3,4,6,7}
那么显然直接返回cur的长度是不可能的,直接返回cur和原始输入A的并集也是不可以的,因为漏掉了3。对于我能考虑到替换res的两种方法,都会导致测试不通过,所以res这个集合的存在是有必要的。
# 连续子数组按位或操作 leetcode-898
#方法一
def subarrayBitwiseORs(A: List[int]) -> int:
n = len(A)
s = {A[0]}
for i in range(0, n):
temp = A[i]
s.add(temp)
for j in range(i+1, n):
temp |= A[j]
s.add(temp)
return len(s)
# 方法二 因为set每次都会判断是否有重复的值 慢 换成列表
def lianxv_002(A: List[int]) -> int:
n = len(A)
s = []
for i in range(0, n):
temp = A[i]
s.append(temp)
for j in range(i+1, n):
temp |= A[j]
s.append(temp)
return len(set(s))
#方法三:动态规划的思想
def lianxv_003(A:List[int]) -> int:
cur = set()
res = set()
for a in A: # a 是要新进来的元素
cur = {a | b for b in cur} | {a}
res |= cur # cur和res取得并集
return len(res)