leetcode-898 子数组按位或操作

我们有一个非负整数数组 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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值