题目描述
给你一个由 正 整数组成的数组 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 <= 105
1 <= nums[i] <= 109
解法
方法一:双指针
我们定义一个变量 $mask$,用于记录当前子数组中的元素按位或的结果,初始时 $mask = 0$。另外,使用双指针 $j$ 和 $i$ 分别指向当前子数组的左右端点,初始时 $i = j = 0$。
接下来,我们从左到右遍历数组 $nums$,对于遍历到的每个元素 $x$:
我们将其与 $mask$ 按位与,如果结果不为 $0$,则说明 $x$ 和 $mask$ 中至少有一个元素的二进制表示中的某一位为 $1$,而另一个元素的二进制表示中的对应位为 $0$,这样的元素对不可能满足题目要求,因此我们需要将 $j$ 右移,直到 $x$ 和 $mask$ 按位与的结果为 $0$ 为止。
此时,我们就找到了一个满足题目要求的子数组,其长度为 $i - j + 1$,我们将其与当前的最长优雅子数组的长度进行比较,如果大于当前的最长优雅子数组的长度,则更新最长优雅子数组的长度。
然后我们将 $mask$ 和 $x$ 按位或,继续遍历下一个元素。
最终,我们得到的最长优雅子数组的长度即为答案。
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。
| class Solution:
def longestNiceSubarray(self, nums: List[int]) -> int:
ans = j = mask = 0
for i, x in enumerate(nums):
while mask & x:
mask ^= nums[j]
j += 1
ans = max(ans, i - j + 1)
mask |= x
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | class Solution {
public int longestNiceSubarray(int[] nums) {
int ans = 0, mask = 0;
for (int i = 0, j = 0; i < nums.length; ++i) {
while ((mask & nums[i]) != 0) {
mask ^= nums[j++];
}
ans = Math.max(ans, i - j + 1);
mask |= nums[i];
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | class Solution {
public:
int longestNiceSubarray(vector<int>& nums) {
int ans = 0, mask = 0;
for (int i = 0, j = 0; i < nums.size(); ++i) {
while (mask & nums[i]) {
mask ^= nums[j++];
}
ans = max(ans, i - j + 1);
mask |= nums[i];
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | func longestNiceSubarray(nums []int) (ans int) {
mask, j := 0, 0
for i, x := range nums {
for ; mask&x != 0; j++ {
mask ^= nums[j]
}
if k := i - j + 1; ans < k {
ans = k
}
mask |= x
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12 | function longestNiceSubarray(nums: number[]): number {
let mask = 0;
let ans = 0;
for (let i = 0, j = 0; i < nums.length; ++i) {
while ((mask & nums[i]) !== 0) {
mask ^= nums[j++];
}
ans = Math.max(ans, i - j + 1);
mask |= nums[i];
}
return ans;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | impl Solution {
pub fn longest_nice_subarray(nums: Vec<i32>) -> i32 {
let mut ans = 0;
let mut mask = 0;
let mut j = 0;
for (i, &x) in nums.iter().enumerate() {
let mut x = x;
while (mask & x) != 0 {
mask ^= nums[j];
j += 1;
}
ans = ans.max(i - j + 1);
mask |= x;
}
ans as i32
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | public class Solution {
public int LongestNiceSubarray(int[] nums) {
int ans = 0, mask = 0;
for (int i = 0, j = 0; i < nums.Length; ++i) {
while ((mask & nums[i]) != 0) {
mask ^= nums[j++];
}
ans = Math.Max(ans, i - j + 1);
mask |= nums[i];
}
return ans;
}
}
|