Skip to content

feat: update 2nd and add 3rd ts solution to lc problem: No.1438 #3160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jun 25, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -1188,4 +1188,236 @@ class Deque<T> {

<!-- solution:end -->

<!-- solution:start -->

### 方法三:滑动窗口 + 双向队列

我们可以使用双向队列维护窗口内的最大值和最小值。我们维护两个双向队列,分别存储窗口内的最大值和最小值的下标。定义两个指针 $l$ 和 $r$ 分别指向窗口的左边界和右边界。

每次向右移动右边界 $r$,判断最大值队列的队尾下标对应的元素是否小于当前元素,如果小于,则将队尾元素出队,直到最大值队列的队尾元素对应的元素不小于当前元素。同理,判断最小值队列的队尾下标对应的元素是否大于当前元素,如果大于,则将队尾元素出队,直到最小值队列的队尾元素对应的元素不大于当前元素。然后,将当前元素的下标入队。

如果最大值队列的队首元素和最小值队列的队首元素的差值大于 $limit$,则向右移动左边界 $l$,然后如果最大值队列的队首元素小于 $l$,则将最大值队列的队首元素出队,如果最小值队列的队首元素小于 $l$,则将最小值队列的队首元素出队。

答案为 $n - l$。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $nums$ 的长度。

<!-- tabs:start -->

#### Python3

```python
class Solution:
def longestSubarray(self, nums: List[int], limit: int) -> int:
maxq = deque()
minq = deque()
l, n = 0, len(nums)
for r, x in enumerate(nums):
while maxq and nums[maxq[-1]] < x:
maxq.pop()
while minq and nums[minq[-1]] > x:
minq.pop()
maxq.append(r)
minq.append(r)
if nums[maxq[0]] - nums[minq[0]] > limit:
l += 1
if maxq[0] < l:
maxq.popleft()
if minq[0] < l:
minq.popleft()
return n - l
```

#### Java

```java
class Solution {
public int longestSubarray(int[] nums, int limit) {
Deque<Integer> maxQ = new ArrayDeque<>();
Deque<Integer> minQ = new ArrayDeque<>();
int n = nums.length;
int l = 0;
for (int r = 0; r < n; ++r) {
while (!maxQ.isEmpty() && nums[maxQ.peekLast()] < nums[r]) {
maxQ.pollLast();
}
while (!minQ.isEmpty() && nums[minQ.peekLast()] > nums[r]) {
minQ.pollLast();
}
maxQ.offerLast(r);
minQ.offerLast(r);
if (nums[maxQ.peekFirst()] - nums[minQ.peekFirst()] > limit) {
++l;
if (maxQ.peekFirst() < l) {
maxQ.pollFirst();
}
if (minQ.peekFirst() < l) {
minQ.pollFirst();
}
}
}
return n - l;
}
}
```

#### C++

```cpp
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
deque<int> max_q;
deque<int> min_q;
int n = nums.size();
int l = 0;

for (int r = 0; r < n; ++r) {
while (!max_q.empty() && nums[max_q.back()] < nums[r]) {
max_q.pop_back();
}
while (!min_q.empty() && nums[min_q.back()] > nums[r]) {
min_q.pop_back();
}
max_q.push_back(r);
min_q.push_back(r);

if (nums[max_q.front()] - nums[min_q.front()] > limit) {
++l;
if (max_q.front() < l) {
max_q.pop_front();
}
if (min_q.front() < l) {
min_q.pop_front();
}
}
}
return n - l;
}
};
```

#### Go

```go
func longestSubarray(nums []int, limit int) int {
var maxq, minq Deque
n := len(nums)
l := 0
for r, x := range nums {
for !maxq.Empty() && nums[maxq.Back()] < x {
maxq.PopBack()
}
for !minq.Empty() && nums[minq.Back()] > x {
minq.PopBack()
}
maxq.PushBack(r)
minq.PushBack(r)

if nums[maxq.Front()]-nums[minq.Front()] > limit {
l++
if maxq.Front() < l {
maxq.PopFront()
}
if minq.Front() < l {
minq.PopFront()
}
}
}
return n - l
}

type Deque struct{ l, r []int }

func (q Deque) Empty() bool {
return len(q.l) == 0 && len(q.r) == 0
}

func (q Deque) Size() int {
return len(q.l) + len(q.r)
}

func (q *Deque) PushFront(v int) {
q.l = append(q.l, v)
}

func (q *Deque) PushBack(v int) {
q.r = append(q.r, v)
}

func (q *Deque) PopFront() (v int) {
if len(q.l) > 0 {
q.l, v = q.l[:len(q.l)-1], q.l[len(q.l)-1]
} else {
v, q.r = q.r[0], q.r[1:]
}
return
}

func (q *Deque) PopBack() (v int) {
if len(q.r) > 0 {
q.r, v = q.r[:len(q.r)-1], q.r[len(q.r)-1]
} else {
v, q.l = q.l[0], q.l[1:]
}
return
}

func (q Deque) Front() int {
if len(q.l) > 0 {
return q.l[len(q.l)-1]
}
return q.r[0]
}

func (q Deque) Back() int {
if len(q.r) > 0 {
return q.r[len(q.r)-1]
}
return q.l[0]
}

func (q Deque) Get(i int) int {
if i < len(q.l) {
return q.l[len(q.l)-1-i]
}
return q.r[i-len(q.l)]
}
```

#### TypeScript

```ts
function longestSubarray(nums: number[], limit: number): number {
const maxq: number[] = [];
const minq: number[] = [];
const n = nums.length;
let l = 0;
for (let r = 0; r < n; ++r) {
while (maxq.length && nums[maxq.at(-1)!] < nums[r]) {
maxq.pop();
}
while (minq.length && nums[minq.at(-1)!] > nums[r]) {
minq.pop();
}
maxq.push(r);
minq.push(r);
if (nums[maxq[0]] - nums[minq[0]] > limit) {
l++;
if (maxq[0] < l) {
maxq.shift();
}
if (minq[0] < l) {
minq.shift();
}
}
}
return n - l;
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
Loading
Loading