leetcode - 898. 子数组按位或操作(使用了集合)

我们有一个非负整数数组 A。

对于每个(连续的)子数组 B = [ A [ i ] , A [ i + 1 ] , . . . , A [ j ] ] ( i < = j ) B = [A[i], A[i+1], ..., A[j]] ( i <= j) B=[A[i],A[i+1],...,A[j]]i<=j,我们对 B 中的每个元素进行按位或操作,获得结果 A [ i ] ∣ A [ i + 1 ] ∣ . . . ∣ A [ j ] A[i] | A[i+1] | ... | A[j] 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 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/bitwise-ors-of-subarrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
————————————
解题思路:使用动态规划,一直超时真是头皮发麻;

d p [ i ] [ j ] dp[i][j] dp[i][j]表示从非负数组 A [ i ] A[i] A[i] A [ j ] A[j] A[j]的子数组进行或操作之后得到的值。

对于 d p [ i ] [ j + 1 ] dp[i][j+1] dp[i][j+1],该子数组使用动态规划求解其或操作之后得到的值,其动态转移方程为:

d p [ i ] [ j + 1 ] = d p [ i ] [ j ] ∣ A [ j + 1 ] dp[i][j+1]=dp[i][j] | A[j+1] dp[i][j+1]=dp[i][j]A[j+1]

因为动态转移方程只用到上一个状态的信息,因此只需要一维数组就能存储所有的信息;

其C++代码如下:

class Solution {
public:
    int subarrayBitwiseORs(vector<int>& a) {
        int length = a.size();
        unordered_set<unsigned int> nums;   #建立一个集合,集合中不会有重复的数字
        int max = 0;
        for(int i=0;i<length;i++)  #找出最大值,用于作为停止条件,避免更多的重复操作
        {
            max |=a[i];
        }
        nums.insert(max);  #最大值必定在子数组或操作中出现,因此存进集合里
        for(int i=0;i<length;i++)
        {
            int bitee = a[i];   #以数组中的每一个数字作为循环的开始
            nums.insert(bitee);
            for(int j=i+1;j<length;j++)
            {
                bitee = bitee|a[j];  #状态转移方程,进行或操作
                if(bitee==max)  #如果达到最大值。避免浪费时间,直接break
                    break;
                if(bitee>a[j])  #如果这一次的或操作得到的值没有增加,则可以跳过
                    nums.insert(bitee);
            }
        }
        return nums.size();  #返回集合里面不同数字的数量
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值