Skip to content

Commit

Permalink
feat: update solutions to lc problem: No.2401 (#3520)
Browse files Browse the repository at this point in the history
No.2401.Longest Nice Subarray
  • Loading branch information
yanglbme authored Sep 13, 2024
1 parent 599ad45 commit f5a275d
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 154 deletions.
97 changes: 44 additions & 53 deletions solution/2400-2499/2401.Longest Nice Subarray/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,15 @@ tags:

### 方法一:双指针

我们定义一个变量 $mask$,用于记录当前子数组中的元素按位或的结果,初始时 $mask = 0$。另外,使用双指针 $j$ 和 $i$ 分别指向当前子数组的左右端点,初始时 $i = j = 0$。
根据题目描述,子数组的每个元素的二进制位上的 $1$ 的位置不能相同,这样才能保证任意两个元素的按位与结果为 $0$。

接下来,我们从左到右遍历数组 $nums$,对于遍历到的每个元素 $x$:
因此,我们可以使用双指针 $l$ 和 $r$ 维护一个滑动窗口,使得窗口内的元素满足题目条件。

我们将其与 $mask$ 按位与,如果结果不为 $0$,则说明 $x$ 和 $mask$ 中至少有一个元素的二进制表示中的某一位为 $1$,而另一个元素的二进制表示中的对应位为 $0$,这样的元素对不可能满足题目要求,因此我们需要将 $j$ 右移,直到 $x$ 和 $mask$ 按位与的结果为 $0$ 为止
我们用一个变量 $\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)$

此时,我们就找到了一个满足题目要求的子数组,其长度为 $i - j + 1$,我们将其与当前的最长优雅子数组的长度进行比较,如果大于当前的最长优雅子数组的长度,则更新最长优雅子数组的长度
遍历结束后,返回答案 $\textit{ans}$ 即可

然后我们将 $mask$ 和 $x$ 按位或,继续遍历下一个元素。

最终,我们得到的最长优雅子数组的长度即为答案。

时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。
时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。

<!-- tabs:start -->

Expand All @@ -87,13 +83,13 @@ tags:
```python
class Solution:
def longestNiceSubarray(self, nums: List[int]) -> int:
ans = j = mask = 0
for i, x in enumerate(nums):
ans = mask = l = 0
for r, x in enumerate(nums):
while mask & x:
mask ^= nums[j]
j += 1
ans = max(ans, i - j + 1)
mask ^= nums[l]
l += 1
mask |= x
ans = max(ans, r - l + 1)
return ans
```

Expand All @@ -103,12 +99,12 @@ class Solution:
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++];
for (int l = 0, r = 0; r < nums.length; ++r) {
while ((mask & nums[r]) != 0) {
mask ^= nums[l++];
}
ans = Math.max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = Math.max(ans, r - l + 1);
}
return ans;
}
Expand All @@ -122,12 +118,12 @@ 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++];
for (int l = 0, r = 0; r < nums.size(); ++r) {
while (mask & nums[r]) {
mask ^= nums[l++];
}
ans = max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = max(ans, r - l + 1);
}
return ans;
}
Expand All @@ -138,15 +134,14 @@ public:
```go
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, 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
}
Expand All @@ -156,14 +151,13 @@ func longestNiceSubarray(nums []int) (ans int) {

```ts
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++];
let [ans, mask] = [0, 0];
for (let l = 0, r = 0; r < nums.length; ++r) {
while (mask & nums[r]) {
mask ^= nums[l++];
}
ans = Math.max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = Math.max(ans, r - l + 1);
}
return ans;
}
Expand All @@ -176,19 +170,16 @@ 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;
let mut l = 0;
for (r, &x) in nums.iter().enumerate() {
while mask & x != 0 {
mask ^= nums[l];
l += 1;
}
ans = ans.max(i - j + 1);
mask |= x;
ans = ans.max((r - l + 1) as i32);
}

ans as i32
ans
}
}
```
Expand All @@ -199,12 +190,12 @@ impl Solution {
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++];
for (int l = 0, r = 0; r < nums.Length; ++r) {
while ((mask & nums[r]) != 0) {
mask ^= nums[l++];
}
ans = Math.Max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = Math.Max(ans, r - l + 1);
}
return ans;
}
Expand Down
97 changes: 44 additions & 53 deletions solution/2400-2499/2401.Longest Nice Subarray/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,15 @@ It can be proven that no longer nice subarray can be obtained, so we return 3.</

### Solution 1: Two Pointers

We define a variable $mask$ to record the bitwise OR result of the elements in the current subarray, initially $mask = 0$. Also, we use two pointers $j$ and $i$ to point to the left and right endpoints of the current subarray, initially $i = j = 0$.
According to the problem description, the position of the binary $1$ in each element of the subarray must be unique to ensure that the bitwise AND result of any two elements is $0$.

Next, we traverse the array $nums$ from left to right. For each element $x$ we encounter:
Therefore, we can use two pointers, $l$ and $r$, to maintain a sliding window such that the elements within the window satisfy the problem's conditions.

We perform a bitwise AND operation between it and $mask$. If the result is not $0$, it means that $x$ and at least one element in $mask$ have a binary representation where a certain bit is $1$, and the corresponding bit in the other element's binary representation is $0$. Such pairs of elements cannot satisfy the problem's requirements, so we need to move $j$ to the right until the bitwise AND result of $x$ and $mask$ is $0$.
We use a variable $\textit{mask}$ to represent the bitwise OR result of the elements within the window. Next, we traverse each element of the array. For the current element $x$, if the bitwise AND result of $\textit{mask}$ and $x$ is not $0$, it means that the current element $x$ has overlapping binary bits with the elements in the window. At this point, we need to move the left pointer $l$ until the bitwise AND result of $\textit{mask}$ and $x$ is $0$. Then, we assign the bitwise OR result of $\textit{mask}$ and $x$ to $\textit{mask}$ and update the answer $\textit{ans} = \max(\textit{ans}, r - l + 1)$.

At this point, we have found a subarray that satisfies the problem's requirements. Its length is $i - j + 1$. We compare it with the length of the current longest elegant subarray. If it is longer than the current longest elegant subarray, we update the length of the longest elegant subarray.
After the traversal, return the answer $\textit{ans}$.

Then we perform a bitwise OR operation between $mask$ and $x$, and continue to the next element.

Finally, the length of the longest elegant subarray we obtain is the answer.

The time complexity is $O(n)$, and the space complexity is $O(1)$. Here, $n$ is the length of the array $nums$.
The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$.

<!-- tabs:start -->

Expand All @@ -87,13 +83,13 @@ The time complexity is $O(n)$, and the space complexity is $O(1)$. Here, $n$ is
```python
class Solution:
def longestNiceSubarray(self, nums: List[int]) -> int:
ans = j = mask = 0
for i, x in enumerate(nums):
ans = mask = l = 0
for r, x in enumerate(nums):
while mask & x:
mask ^= nums[j]
j += 1
ans = max(ans, i - j + 1)
mask ^= nums[l]
l += 1
mask |= x
ans = max(ans, r - l + 1)
return ans
```

Expand All @@ -103,12 +99,12 @@ class Solution:
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++];
for (int l = 0, r = 0; r < nums.length; ++r) {
while ((mask & nums[r]) != 0) {
mask ^= nums[l++];
}
ans = Math.max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = Math.max(ans, r - l + 1);
}
return ans;
}
Expand All @@ -122,12 +118,12 @@ 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++];
for (int l = 0, r = 0; r < nums.size(); ++r) {
while (mask & nums[r]) {
mask ^= nums[l++];
}
ans = max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = max(ans, r - l + 1);
}
return ans;
}
Expand All @@ -138,15 +134,14 @@ public:
```go
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, 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
}
Expand All @@ -156,14 +151,13 @@ func longestNiceSubarray(nums []int) (ans int) {

```ts
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++];
let [ans, mask] = [0, 0];
for (let l = 0, r = 0; r < nums.length; ++r) {
while (mask & nums[r]) {
mask ^= nums[l++];
}
ans = Math.max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = Math.max(ans, r - l + 1);
}
return ans;
}
Expand All @@ -176,19 +170,16 @@ 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;
let mut l = 0;
for (r, &x) in nums.iter().enumerate() {
while mask & x != 0 {
mask ^= nums[l];
l += 1;
}
ans = ans.max(i - j + 1);
mask |= x;
ans = ans.max((r - l + 1) as i32);
}

ans as i32
ans
}
}
```
Expand All @@ -199,12 +190,12 @@ impl Solution {
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++];
for (int l = 0, r = 0; r < nums.Length; ++r) {
while ((mask & nums[r]) != 0) {
mask ^= nums[l++];
}
ans = Math.Max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = Math.Max(ans, r - l + 1);
}
return ans;
}
Expand Down
12 changes: 6 additions & 6 deletions solution/2400-2499/2401.Longest Nice Subarray/Solution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ 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++];
for (int l = 0, r = 0; r < nums.size(); ++r) {
while (mask & nums[r]) {
mask ^= nums[l++];
}
ans = max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = max(ans, r - l + 1);
}
return ans;
}
};
};
12 changes: 6 additions & 6 deletions solution/2400-2499/2401.Longest Nice Subarray/Solution.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,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++];
for (int l = 0, r = 0; r < nums.Length; ++r) {
while ((mask & nums[r]) != 0) {
mask ^= nums[l++];
}
ans = Math.Max(ans, i - j + 1);
mask |= nums[i];
mask |= nums[r];
ans = Math.Max(ans, r - l + 1);
}
return ans;
}
}
}
15 changes: 7 additions & 8 deletions solution/2400-2499/2401.Longest Nice Subarray/Solution.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
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, 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
}
}
Loading

0 comments on commit f5a275d

Please sign in to comment.