diff --git a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README.md b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README.md index 02b31b4a8b6d7..313692f014fd4 100644 --- a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README.md +++ b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README.md @@ -1188,4 +1188,238 @@ class Deque { + + +### 方法三:滑动窗口 + 双向队列 + +我们可以使用双向队列维护窗口内的最大值和最小值。我们维护两个双向队列,分别存储窗口内的最大值和最小值的下标。定义两个指针 $l$ 和 $r$ 分别指向窗口的左边界和右边界。 + +每次向右移动右边界 $r$,判断最大值队列的队尾下标对应的元素是否小于当前元素,如果小于,则将队尾元素出队,直到最大值队列的队尾元素对应的元素不小于当前元素。同理,判断最小值队列的队尾下标对应的元素是否大于当前元素,如果大于,则将队尾元素出队,直到最小值队列的队尾元素对应的元素不大于当前元素。然后,将当前元素的下标入队。 + +如果最大值队列的队首元素和最小值队列的队首元素的差值大于 $limit$,则向右移动左边界 $l$,然后如果最大值队列的队首元素小于 $l$,则将最大值队列的队首元素出队,如果最小值队列的队首元素小于 $l$,则将最小值队列的队首元素出队。 + +答案为 $n - l$。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $nums$ 的长度。 + + + +#### 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 maxQ = new ArrayDeque<>(); + Deque 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& nums, int limit) { + deque max_q; + deque 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 n = nums.length; + let [h1, t1] = [0, -1]; + let [h2, t2] = [0, -1]; + let l = 0; + const maxq = Array(n); + const minq = Array(n); + for (let r = 0; r < n; ++r) { + while (h1 <= t1 && nums[maxq[t1]] < nums[r]) { + --t1; + } + while (h2 <= t2 && nums[minq[t2]] > nums[r]) { + --t2; + } + maxq[++t1] = r; + minq[++t2] = r; + if (nums[maxq[h1]] - nums[minq[h2]] > limit) { + ++l; + if (maxq[h1] < l) { + ++h1; + } + if (minq[h2] < l) { + ++h2; + } + } + } + return n - l; +} +``` + + + + + diff --git a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README_EN.md b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README_EN.md index 4bb1e6cff94f4..6a096d16d3328 100644 --- a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README_EN.md +++ b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/README_EN.md @@ -1183,4 +1183,238 @@ class Deque { + + +### Solution 3: Sliding Window + Deque + +We can use a deque to maintain the maximum and minimum values within the window. We maintain two deques, one for storing the indices of the maximum values and the other for the minimum values within the window. Define two pointers $l$ and $r$ to point to the left and right boundaries of the window, respectively. + +Each time we move the right boundary $r$ to the right, we check if the element corresponding to the tail index of the maximum value deque is less than the current element. If it is, we dequeue the tail element until the element corresponding to the tail of the maximum value deque is not less than the current element. Similarly, we check if the element corresponding to the tail index of the minimum value deque is greater than the current element. If it is, we dequeue the tail element until the element corresponding to the tail of the minimum value deque is not greater than the current element. Then, we enqueue the current element's index. + +If the difference between the elements at the front of the maximum value deque and the minimum value deque is greater than $limit$, then we move the left boundary $l$ to the right. If the element at the front of the maximum value deque is less than $l$, we dequeue the front element of the maximum value deque. Similarly, if the element at the front of the minimum value deque is less than $l$, we dequeue the front element of the minimum value deque. + +The answer is $n - l$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $nums$. + + + +#### 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 maxQ = new ArrayDeque<>(); + Deque 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& nums, int limit) { + deque max_q; + deque 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 n = nums.length; + let [h1, t1] = [0, -1]; + let [h2, t2] = [0, -1]; + let l = 0; + const maxq = Array(n); + const minq = Array(n); + for (let r = 0; r < n; ++r) { + while (h1 <= t1 && nums[maxq[t1]] < nums[r]) { + --t1; + } + while (h2 <= t2 && nums[minq[t2]] > nums[r]) { + --t2; + } + maxq[++t1] = r; + minq[++t2] = r; + if (nums[maxq[h1]] - nums[minq[h2]] > limit) { + ++l; + if (maxq[h1] < l) { + ++h1; + } + if (minq[h2] < l) { + ++h2; + } + } + } + return n - l; +} +``` + + + + + diff --git a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.cpp b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.cpp new file mode 100644 index 0000000000000..a67fa331487dd --- /dev/null +++ b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.cpp @@ -0,0 +1,31 @@ +class Solution { +public: + int longestSubarray(vector& nums, int limit) { + deque max_q; + deque 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; + } +}; diff --git a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.go b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.go new file mode 100644 index 0000000000000..67b365b42eaa0 --- /dev/null +++ b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.go @@ -0,0 +1,83 @@ +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)] +} diff --git a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.java b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.java new file mode 100644 index 0000000000000..ec3f7644d11db --- /dev/null +++ b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.java @@ -0,0 +1,28 @@ +class Solution { + public int longestSubarray(int[] nums, int limit) { + Deque maxQ = new ArrayDeque<>(); + Deque 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; + } +} diff --git a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.py b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.py new file mode 100644 index 0000000000000..7d82d08c1f322 --- /dev/null +++ b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.py @@ -0,0 +1,19 @@ +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 diff --git a/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.ts b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.ts new file mode 100644 index 0000000000000..8686d511a5485 --- /dev/null +++ b/solution/1400-1499/1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit/Solution3.ts @@ -0,0 +1,28 @@ +function longestSubarray(nums: number[], limit: number): number { + const n = nums.length; + let [h1, t1] = [0, -1]; + let [h2, t2] = [0, -1]; + let l = 0; + const maxq = Array(n); + const minq = Array(n); + for (let r = 0; r < n; ++r) { + while (h1 <= t1 && nums[maxq[t1]] < nums[r]) { + --t1; + } + while (h2 <= t2 && nums[minq[t2]] > nums[r]) { + --t2; + } + maxq[++t1] = r; + minq[++t2] = r; + if (nums[maxq[h1]] - nums[minq[h2]] > limit) { + ++l; + if (maxq[h1] < l) { + ++h1; + } + if (minq[h2] < l) { + ++h2; + } + } + } + return n - l; +}