我们有一个非负整数数组 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(); #返回集合里面不同数字的数量
}
};