前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【DP】898. Bitwise ORs of Subarrays

【DP】898. Bitwise ORs of Subarrays

作者头像
echobingo
发布2019-06-02 15:04:34
3870
发布2019-06-02 15:04:34
举报
题目描述:

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:
代码语言:javascript
复制
Input: [0]
Output: 1
Explanation: 
There is only one possible result: 0.
Example 2:
代码语言:javascript
复制
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:
代码语言:javascript
复制
Input: [1,2,4]
Output: 6
Explanation: 
The possible results are 1, 2, 3, 4, 6, and 7.

Note:

代码语言:javascript
复制
1 <= A.length <= 50000
0 <= A[i] <= 10^9
解题思路:

这道题很好理解,但是时间复杂度要求很高,就连普通DP都会超时,容我慢慢道来。

1、直接暴力(TLE):

  • 尝试所有可能的子数组 n^2;
  • 对每个子数组计算 Or 操作。

这样,时间复杂度 O(n^3),空间复杂度 O(1),肯定不行,想都不用想先pass。

2、普通DP(我使用的方法,但是很可惜还是 TLE 了):

  • 用 dp[i][j] 记录子串 i~j 之间的 Or 操作结果,即 dp[i][j] = A[i] | A[i+1] | ... | A[j],其中 i >= j;
  • 容易找到转移方程 dp[i][j] = dp[i][j-1] + A[j]
  • 结果为 ans = len(set(dp))

这样,时间复杂度 O(n^2),空间复杂度 O(n^2),还是超时了......

3、高级DP(AC):

  • dp[i] 表示以 A[i] 结尾的所有子数组的 Or 结果,其实是个 set。
  • 转移方程式:dp[i] = [(b | A[i]) for b in dp[i-1]] + A[i],即以 A[i] 结尾的所有子数组 Or 结果等于以 A[i-1] 结尾的所有子数组 Or 结果,和当前的 A[i] 进行 Or 操作,再加上 A[i] 这个结果。注意: len(dp) <= 32,后面会给出证明。
  • ans = len(set(dp))

这时,时间复杂度 O(32*n),空间复杂度 O(32*n),接受。

证明:为什么方法 3 中的 len(dp) <= 32 ? dp[i] = { A[i], A[i]|A[i-1], A[i]|A[i-1]|A[i-2], … , A[i]|A[i-1]|…|A[0] },这个序列单调递增,通过把 A[i] 中的 0 变成 1。A[i] 最多有 32 个 0,所以这个集合的大小 <= 32。 举例:最坏情况 A = [8, 4, 2, 1, 0],都是 2^k。 A[5] = 0,dp[5] = { 0, 0|1, 0|1|2, 0|1|2|4, 0|1|2|4| } = { 0, 1, 3, 7, 15 }.

Python3 实现:
方法2(TLE):
代码语言:javascript
复制
class Solution:
    def subarrayBitwiseORs(self, A: List[int]) -> int:
        lens = len(A)
        dp = [[0] * lens for _ in range(lens)]
        res = set()
        for i in range(lens):
            dp[i][i] = A[i]
            res.add(dp[i][i])
            for j in range(i+1, lens):
                dp[i][j] = dp[i][j-1] | A[j]
                res.add(dp[i][j])
        return len(res)
方法3(AC):
代码语言:javascript
复制
class Solution(object):
    def subarrayBitwiseORs(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        res = set()
        cur = set()  # 保存上一次的结果
        for a in A:
            cur = {n | a for n in cur} | {a} 
            res |= cur  # 更新结果
        return len(res)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.06.01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述:
    • Example 1:
      • Example 2:
        • Example 3:
        • 解题思路:
        • Python3 实现:
          • 方法2(TLE):
            • 方法3(AC):
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档