题目描述
给你一个由 正 整数组成的数组 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
解法
方法一:双指针
根据题目描述,子数组的每个元素的二进制位上的 $1$ 的位置不能相同,这样才能保证任意两个元素的按位与结果为 $0$。
因此,我们可以使用双指针 $l$ 和 $r$ 维护一个滑动窗口,使得窗口内的元素满足题目条件。
我们用一个变量 $\textit{mask}$ 来表示窗口内的元素的按位或的结果,接下来,遍历数组的每个元素。对于当前元素 $x$,如果 $\textit{mask}$ 和 $x$ 的按位与结果不为 $0$,说明当前元素 $x$ 与窗口内的元素有重复的二进制位,此时需要移动左指针 $l$,直到 $\textit{mask}$ 和 $x$ 的按位与结果为 $0$。然后,我们将 $\textit{mask}$ 和 $x$ 的按位或的结果赋值给 $\textit{mask}$,并更新答案 $\textit{ans} = \max(\textit{ans}, r - l + 1)$。
遍历结束后,返回答案 $\textit{ans}$ 即可。
时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。
| class Solution:
def longestNiceSubarray(self, nums: List[int]) -> int:
ans = mask = l = 0
for r, x in enumerate(nums):
while mask & x:
mask ^= nums[l]
l += 1
mask |= x
ans = max(ans, r - l + 1)
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 l = 0, r = 0; r < nums.length; ++r) {
while ((mask & nums[r]) != 0) {
mask ^= nums[l++];
}
mask |= nums[r];
ans = Math.max(ans, r - l + 1);
}
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 l = 0, r = 0; r < nums.size(); ++r) {
while (mask & nums[r]) {
mask ^= nums[l++];
}
mask |= nums[r];
ans = max(ans, r - l + 1);
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12 | func longestNiceSubarray(nums []int) (ans int) {
mask, l := 0, 0
for r, x := range nums {
for mask&x != 0 {
mask ^= nums[l]
l++
}
mask |= x
ans = max(ans, r-l+1)
}
return
}
|
| function longestNiceSubarray(nums: number[]): number {
let [ans, mask] = [0, 0];
for (let l = 0, r = 0; r < nums.length; ++r) {
while (mask & nums[r]) {
mask ^= nums[l++];
}
mask |= nums[r];
ans = Math.max(ans, r - l + 1);
}
return ans;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | impl Solution {
pub fn longest_nice_subarray(nums: Vec<i32>) -> i32 {
let mut ans = 0;
let mut mask = 0;
let mut l = 0;
for (r, &x) in nums.iter().enumerate() {
while mask & x != 0 {
mask ^= nums[l];
l += 1;
}
mask |= x;
ans = ans.max((r - l + 1) as i32);
}
ans
}
}
|
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 l = 0, r = 0; r < nums.Length; ++r) {
while ((mask & nums[r]) != 0) {
mask ^= nums[l++];
}
mask |= nums[r];
ans = Math.Max(ans, r - l + 1);
}
return ans;
}
}
|