581. 最短无序连续子数组

题目描述

从数组中找一个连续子数字,对子数组升序的时候,数组就是升序的。
求最短的子数组的长度?

f1排序+双指针

基本分析

  1. 如果排序后怎么找?左边第一个不等的点和右边第一个不等的点

代码

class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
nums_sorted = sorted(nums)
n = len(nums)
l, r = 0, n-1
while l <= r and nums[l] == nums_sorted[l]:
l += 1
while r >= l and nums[r] == nums_sorted[r]:
r -= 1
return r - l + 1

总结

  1. 这里为啥用 <=, 不是 < ? 待明确
f2-双指针一次遍历

基本分析

  1. k遍历的区间?l,r
  2. 指针移动的方向?i从l到0,j从r到n-1
  3. 每次枚举k,什么时候需要更新i或者j?j位置的值比左边的最小小或者比右边的最大大
  4. 如果需要维护,怎么维护?一直往左或者往右找,找到第一个<=nums[k]的值,或者第一个>=nums[k]的值
  5. 越界的情况怎么处理?i到头给-inf,j到头给inf,这样判断的时候都会满足
  6. 结果怎么计算?区分相等或者不等的情况

代码

class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
n = len(nums)
i, j = 0, n-1
while i < j and nums[i] <= nums[i+1]:
i += 1
while i < j and nums[j] >= nums[j-1]:
j -= 1
# 这里找到的i和j都是满足单调条件的
l, r = i, j
# 最开始是1增结尾,3增开始
curmin, curmax = nums[i], nums[j]
# 为什么l是满足条件的,为啥要从l遍历?可能nums[l] > max
for k in range(l, r+1):
# 如果当前值比左边的小值小,小值的位置不保
if nums[k] < curmin:
while i >= 0 and nums[i] > nums[k]:
i -= 1
# 出来以后i可能是0,可能是找到了满足nums[i] <= nums[k]的索引
if i < 0:
# 足够小了,不用再比了
curmin = -inf
else:
# 否则更新当前小值
curmin = nums[i]
if nums[k] > curmax:
while j <= n-1 and nums[j] < nums[k]:
j += 1
# 找到的合适的点可能是结尾,可能是真的有
if j > n-1:
# 别找了
curmax = inf
else:
curmax = nums[j]
# 遍历完以后,可能ij就是一个点,也可能不是
if i == j:
return 0
else:
return (j-1) - (i+1) + 1

总结

  1. 可能可以用单调栈处理,需要考虑下
posted @   zhangk1988  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示