找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2070

积分

0

好友

296

主题
发表于 昨天 07:52 | 查看: 3| 回复: 0

刚看到社交媒体上分享的一个职场事件:一位技术总监在拿到45万年终奖后,却突然提出了离职。起初同事们都猜测他是被竞争对手高薪挖走,但背后的真实原因令人意外:他长期负责的两个核心项目,在毫不知情的情况下被公司悄悄转移给了新空降的领导,而他自己的名字甚至没有出现在项目列表上。

技术总监离职事件社交媒体截图

这个事件中,金钱的补偿与职业的尊重被割裂了。年终奖或许是对过去贡献的肯定,但对于技术人而言,长期投入和主导的项目才是未来发展的核心筹码。当所有的成绩被一笔抹去,传递出的信号是:无论你在这里干多久,都可能随时被替换。

从公司角度看,这种做法也显得短视。真正愿意为公司创造价值的骨干一旦心寒,剩下的可能只有冷冰冰的KPI数字,团队将失去为之拼搏的动力。

这也引发了一个更广泛的思考:当职业发展遇到阻碍时,如何评估与决策?也许适时地寻求新的机会或平台,也是一种理性的职业规划。关于职业路径的更多探讨,可以关注云栈社区的职场板块。

金钱固然重要,但职业尊严与发展空间同样不可或缺。遇到触及原则底线的公司,及时止损未必是坏事。

算法题:缺失的区间

不知道你有没有这样的经历:业务系统中一个自增ID用了一段时间后,中间被人为删除了一些记录,导致ID序列不再连续。这时产品经理可能会跑来紧张地问:“这几天的订单数据是不是丢失了?”你一查,发现数据其实都在,只是ID不连续而已。但为了解释清楚,往往需要把缺失的ID区间都找出来,这个过程如果手动计算,确实有点繁琐。

其实,很多这类“查漏补缺”的需求,其核心就是今天要讨论的算法题:缺失的区间

让我们来抽象一下问题:
想象有一条整数轴,从 lowerupper,中间有一些数字已经被“占用”了。题目会给你一个有序且元素互不重复的数组 nums,里面就是这些已经存在的数字。
你的任务就是:找出在 [lower, upper] 这个完整范围内,没有出现过的那些数字段,并将每一段整理成一个区间返回。

来看一个具体例子:

  • lower = 0, upper = 9
  • nums = [0, 1, 3, 7, 8]

那么缺失的部分就是:

  • 数字 2 单独一个。
  • 数字 4, 5, 6 连成一段。
  • 数字 9 单独一个。

通常题目要求用字符串列表来表示结果,像这样:["2", "4->6", "9"]

目标很明确,接下来我们聊聊解题思路,而不是一上来就写代码。

我当时是这么思考的:
你可以想象自己拿着一个小本子,从 lower 这个起点开始向右“巡视”。我们记录一个 prev 变量,表示“上一次遇到的那个已存在的数字”。
每当你遇到数组 nums 中的一个数字 x 时,就检查一下 prev 和这个 x 之间有没有“空隙”:

  • 如果 x == prev + 1,说明 prevx 是紧挨着的,中间没有缺失的数字,继续往前走。
  • 如果 x > prev + 1,那么恭喜你,找到了一个洞!缺失的区间就是 [prev + 1, x - 1]

然后把 prev 更新为当前的 x,继续巡视下一个数字。

这里有两个边界情况需要特殊处理:

  1. 左边界:可能一开始就缺数字。例如 lower=1, nums=[3,4],那么 [1,2] 这个区间就是缺失的。
  2. 右边界:最后面也可能缺数字,就像上面例子里的 9

如何优雅地统一处理这些边界呢?有一个非常实用的小技巧:

  • 初始化时,不把 prev 设为 lower,而是设为 lower - 1
  • 在循环遍历时,我们不仅遍历原数组 nums,最后再人为地追加一个 upper + 1 作为“虚拟的最后一个已存在数字”。

这样一来,逻辑就变得非常顺畅:

  • 如果左边一开始就缺,那么遇到的第一个 x 就会大于 prev + 1,你自然能计算出缺失区间 [lower, x - 1]
  • 最后追加的那个 upper + 1 会帮助我们“顺带”算出右边界缺失的部分。

这种在数组末尾添加一个“哨兵”值的做法,在解决算法与数据结构相关的很多问题中都特别常见,是一个值得掌握的技巧。

下面直接看代码实现,核心逻辑其实就十来行。我们使用Python来演示:

from typing import List

def format_range(start: int, end: int) -> str:
    """
    把区间格式化成题目要求的样子:
    - 单个数字:'5'
    - 一段区间:'2->6'
    """
    if start == end:
        return str(start)
    return f"{start}->{end}"

def find_missing_ranges(nums: List[int], lower: int, upper: int) -> List[str]:
    res: List[str] = []
    # 上一个“已经存在的数”,先放 lower - 1 当哨兵
    prev = lower - 1

    # 在原数组后面拼一个 upper + 1 的虚拟元素,统一处理右边边界
    for x in nums + [upper + 1]:
        # 注意只看落在 [lower, upper] 范围里的
        if x < lower:
            # 比 lower 小的直接略过
            prev = x
            continue
        if x > upper + 1:
            # 超出右边很多就没必要看了
            x = upper + 1

        # 如果 prev 和 x 之间有“缝”,那就是一个缺失区间
        if x - prev >= 2:
            start = prev + 1
            end = x - 1
            # 再裁一下,保证区间落在 [lower, upper] 内
            start = max(start, lower)
            end = min(end, upper)
            if start <= end:
                res.append(format_range(start, end))
        prev = x

    return res

你可以运行几个测试用例来验证:

print(find_missing_ranges([0, 1, 3, 7, 8], 0, 9))
# 输出:['2', '4->6', '9']

print(find_missing_ranges([], 1, 5))
# 输出:['1->5']

print(find_missing_ranges([1, 2, 3], 1, 3))
# 输出:[]

掌握了这个思路,以后遇到所有“查找缺失部分”的问题,基本都可以在这个基础上进行变通。希望这个从职场故事引申出的算法小技巧对你有用。想了解更多技术讨论和资源分享,欢迎来云栈社区交流。




上一篇:Java Set集合全面指南:HashSet、LinkedHashSet与TreeSet核心用法与线程安全实践
下一篇:深入解析Python没有main函数的原因及其入口设计哲学
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-11 14:24 , Processed in 0.257103 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表