LeetCode 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit - 亚马逊高频题29

给定一个整数数组nums和一个整数limit,需要找到满足任意两个数差的绝对值小于等于limit的最长子数组。通过移动窗口法和堆数据结构,可以高效地求解此问题,避免暴力解法的O(n^2)时间复杂度。在滑动窗口过程中,维护最大堆和最小堆,确保窗口内最大值和最小值的差不超过限制,从而找到最长符合条件的子数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an array of integers nums and an integer limit, return the size of the longest non-empty subarray such that the absolute difference between any two elements of this subarray is less than or equal to limit.

Example 1:

Input: nums = [8,2,4,7], limit = 4
Output: 2 
Explanation: All subarrays are: 
[8] with maximum absolute diff |8-8| = 0 <= 4.
[8,2] with maximum absolute diff |8-2| = 6 > 4. 
[8,2,4] with maximum absolute diff |8-2| = 6 > 4.
[8,2,4,7] with maximum absolute diff |8-2| = 6 > 4.
[2] with maximum absolute diff |2-2| = 0 <= 4.
[2,4] with maximum absolute diff |2-4| = 2 <= 4.
[2,4,7] with maximum absolute diff |2-7| = 5 > 4.
[4] with maximum absolute diff |4-4| = 0 <= 4.
[4,7] with maximum absolute diff |4-7| = 3 <= 4.
[7] with maximum absolute diff |7-7| = 0 <= 4. 
Therefore, the size of the longest subarray is 2.

Example 2:

Input: nums = [10,1,2,4,7,2], limit = 5
Output: 4 
Explanation: The subarray [2,4,7,2] is the longest since the maximum absolute diff is |2-7| = 5 <= 5.

Example 3:

Input: nums = [4,2,2,2,4,4,2,2], limit = 0
Output: 3

Constraints:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^9
  • 0 <= limit <= 10^9

题目给定一个整型数组nums和一个整数limit,要求找到一个最长的子数组,使得该子数组中的任意两个数的差的绝对值都小于等于limit。

我们知道数组中任意两个数的差的绝对值的范围都不会超过数组中的最大值与最小值的差,因此我们只要关心子数组中的最大值和最小值,知道最大值与最小值的差不超过limit就符合题目要求。本题的暴力解法就是,就是用两个循环找出从任意一个位置出发满足条件的所有最长子数组。暴力解法的时间复杂度是O(n^2)会超时。

关于子数组的问题,最常用的一种解法就是移动窗口(Sliding Window)法。所谓滑动窗口法就是用两个指针,一个指向窗口的左边另一个指向窗口的右边,从两个指针同时指向数组的第一个位置开始,为了使得窗口长度尽量长,右指针就要尽量的往右移动,在移动的过程维护窗口内的最大值和最小值,一旦最大值与最小值的差超过limit,右指针就要停止移动,这时的窗口长度减1就是当前满足条件的最长子数组。这时就得开始移动左指针即把窗口左边数剔除,直到剔除掉了最大值或最小值使得窗口重新满足条件为止。本题的难点在于,在移动左指针时如何知道何时剔除了最大值或最小值,又该如何知道窗口中新的最大值和最小值。于是乎很自然的想到了最大堆和最小堆,在移动窗口的同时维护一个最大堆和最小堆(堆的元素是数组值和数组索引),那我们就可以快速地知道到任何时候窗口中的最大值和最小值的位置了。在右指针每向右移动一步时,把当前位置的数值和索引放入最大堆和最小堆中,然后判断两个堆的顶部的数值差(即最大值与最小值的差)是否超过limit,如果超过说明此时需要移动窗口的左指针了,左指针至少要移动到窗口左边第一次出现最大值或最小值的下一个位置,由于两个堆同时也存放了索引号,因此可以快速知道左指针移动的下一个位置,在左指针移动到下个位置后,需要将最大堆和最小堆顶部且位置是在左指针新位置的左边的数从两个堆里移除(这里没必要把两个堆里的所有在左指针新位置左边的数移除,因此最大堆里的较小数和最小堆里的较大数都不影响结果)。

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        maxHeap, minHeap = [], []
        res = 1
        i = 0
        for j in range(len(nums)):
            heapq.heappush(maxHeap, (-nums[j], j))
            heapq.heappush(minHeap, (nums[j], j))
            if -maxHeap[0][0] - minHeap[0][0] > limit:
                i = min(maxHeap[0][1], minHeap[0][1]) + 1
                while maxHeap and maxHeap[0][1] < i:
                    heapq.heappop(maxHeap)
                while minHeap and minHeap[0][1] < i:
                    heapq.heappop(minHeap)
            res = max(res, j - i + 1)
        return res

### LeetCode Hot 100 Problems 列表 LeetCode 的热门目列表通常由社区投票选出,涵盖了各种难度级别的经典编程挑战。这些目对于准备技术面试非常有帮助。以下是部分 LeetCode 热门 100 目列表: #### 数组与字符串 1. **两数之和 (Two Sum)** 2. **三数之和 (3Sum)** 3. **无重复字符的最长子串 (Longest Substring Without Repeating Characters)** 4. **寻找两个正序数组的中位数 (Median of Two Sorted Arrays)** #### 动态规划 5. **爬楼梯 (Climbing Stairs)** 6. **不同的二叉搜索树 (Unique Binary Search Trees)** 7. **最大子序列和 (Maximum Subarray)** #### 字符串处理 8. **有效的括号 (Valid Parentheses)** 9. **最小覆盖子串 (Minimum Window Substring)** 10. **字母异位词分组 (Group Anagrams)** #### 图论 11. **岛屿数量 (Number of Islands)** 12. **课程表 II (Course Schedule II)** #### 排序与查找 13. **最接近原点的 K 个点 (K Closest Points to Origin)** 14. **接雨水 (Trapping Rain Water)** 15. **最长连续序列 (Longest Consecutive Sequence)[^2]** #### 堆栈与队列 16. **每日温度 (Daily Temperatures)** 17. **滑动窗口最大值 (Sliding Window Maximum)** #### 树结构 18. **验证二叉搜索树 (Validate Binary Search Tree)** 19. **二叉树的最大路径和 (Binary Tree Maximum Path Sum)** 20. **从前序与中序遍历序列构造二叉树 (Construct Binary Tree from Preorder and Inorder Traversal)** #### 并查集 21. **冗余连接 II (Redundant Connection II)** #### 贪心算法 22. **跳跃游戏 (Jump Game)** 23. **分割等和子集 (Partition Equal Subset Sum)** #### 双指针技巧 24. **环形链表 II (Linked List Cycle II)[^1]** 25. **相交链表 (Intersection of Two Linked Lists)** #### 其他重要目 26. **LRU缓存机制 (LRU Cache)** 27. **打家劫舍系列 (House Robber I & II)** 28. **编辑距离 (Edit Distance)** 29. **单词拆分 (Word Break)** 此列表并非官方发布版本而是基于社区反馈整理而成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值