给你一个由 正 整数组成的数组 nums
。
如果 nums
的子数组中位于 不同 位置的每对元素按位 与(AND)运算的结果等于 0
,则称该子数组为 优雅 子数组。
返回 最长 的优雅子数组的长度。
子数组 是数组中的一个 连续 部分。
注意:长度为 1
的子数组始终视作优雅子数组。
示例 1:
输入:nums = [1,3,8,48,10] 输出:3 解释:最长的优雅子数组是 [3,8,48] 。子数组满足题目条件: - 3 AND 8 = 0 - 3 AND 48 = 0 - 8 AND 48 = 0 可以证明不存在更长的优雅子数组,所以返回 3 。
示例 2:
输入:nums = [3,1,5,11,13] 输出:1 解释:最长的优雅子数组长度为 1 ,任何长度为 1 的子数组都满足题目条件。
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9
提示 1
What is the maximum possible length of a nice subarray?
提示 2
The length of the longest nice subarray cannot exceed 30. Why is that?
解法:滑动窗口
子数组中每对元素按位 与(AND)&运算的结果等于 0,即
任意两个元素对应的集合的交集为空。
& | 按位与,如果相对应位都是1,则结果为1,否则为0 |
|
| | 按位或,如果相对应位都是 0,则结果为 0,否则为 1 |
|
^ | 按位异或,如果相对应位值相同,则结果为0,否则为1 |
|
~ | 按位取反,翻转操作数的每一位,即0变成1,1变成0 |
|
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数 | |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 | |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 |
1 byte = 8 bit
java 中 int : 4 byte = 32 bit, long : 8 byte = 64 bit
子数组不可能有两个奇数(奇数的二进制数最低位为 1),否则这两个数按位与 & 是大于 0 的。
因为1 <= nums[i] <= 10^9,10^9的二进制数是 111011100110101100101000000000,长度为30.所以在本题的数据范围下,优雅子数组的长度不会超过30.
例如子数组为 [2^0,2^1,2^2,⋯ ,2^29],我们无法再加入一个数 x,使 x 与子数组中的任何一个数按位与 & 均为0。
代码实现时,可以把在子数组中的元素按位或 | 起来(求并集),这样可以 O(1) 判断当前元素是否与前面的元素按位与 & 的结果为 0(交集为空)。
class Solution {
public int longestNiceSubarray(int[] nums) {
int ans = 0;
int window = 0;
int left = 0;
int right = 0;
while (right < nums.length) {
while ((window & nums[right]) != 0) {
window ^= nums[left];
left++;
}
window |= nums[right];
ans = Math.max(ans, right - left + 1);
right++;
}
return ans;
}
}
复杂度分析
- 时间复杂度:O(n),n 是 数组 的长度。
- 空间复杂度:O(1)。