算法practice1

6次阅读
没有评论

 

https://github.com/CyC2018/CS-Notes/blob/master/notes/3.%20%E6%95%B0%E7%BB%84%E4%B8%AD%E9%87%8D%E5%A4%8D%E7%9A%84%E6%95%B0%E5%AD%97.md

你给出的这段代码展示了一个非常经典的**原地置换(In-place Swap)**算法。这种技巧在处理“数组元素范围在 $0$$n-1$ 之间”的问题时非常高效。

下面为你详细拆解其时空复杂度的分析逻辑:


1. 时间复杂度:$O(n)$

初看代码,你可能会发现一个 for 循环嵌套了一个 while 循环,直觉上容易误判为 $O(n^2)$。但实际上,它是 均摊 $O(n)$

为什么是 $O(n)$

  • 核心逻辑:每一次 swap 操作,都会把至少一个数字送到它“应该在”的位置(即 nums[i] == i)。

  • 归位原则:一旦一个数字被送到了正确的位置,它在后续的遍历中就不会再被移动。

  • 计数分析:虽然 while 循环可能在某一次执行中循环多次,但对于长度为 $n$ 的数组,最多只需要 $n-1$ 次交换,就能让所有数字各就各位(或者发现重复)。

  • 结论:每个元素最多被访问和交换常数次,因此总的时间复杂度是 $O(n)$


2. 空间复杂度:$O(1)$

这个比较直观,但也是该算法的精妙之处。

  • 原地操作:算法直接在输入的 nums 数组上进行交换和比较。

  • 额外变量:除了循环变量 i 和交换时用到的临时变量 t,没有申请任何与输入规模 $n$ 相关的额外空间(如 HashSet 或临时数组)。

  • 结论:空间复杂度为极优的 $O(1)$


3. 代码小瑕疵纠正

你提供的代码段中有一个小的逻辑冗余和错误,我帮你标注并优化了一下:

Java

public int duplicate(int[] nums) {
    if (nums == null || nums.length <= 1) return -1;

    for (int i = 0; i < nums.length; i++) {
        // while 循环保证将 nums[i] 换到它正确的位置上
        while (nums[i] != i) {
            // 如果要交换的目标位置已经有了正确的数,说明抓到重复的了!
            if (nums[i] == nums[nums[i]]) {
                return nums[i];
            }
            // 交换
            swap(nums, i, nums[i]);
        }
        // 注意:原代码这里多了一个 swap(nums, i, nums[i]),是不需要的
    }
    return -1;
}

关键点拨:

  1. 死循环风险:原代码 while 块后的那个 swap 是多余的,且逻辑上容易让人困惑。

  2. 核心判断if (nums[i] == nums[nums[i]]) 是灵魂。它的意思是:我手里抓着一个 $2$,我想把它放回“老家”(索引为 $2$ 的位置),结果发现“老家”已经住着一个 $2$ 了。嘿,这就是重复!


4. 字节面试避坑指南

如果你在面试中写出这个解法,面试官通常会追问:

  • “如果要求不能修改原数组怎么办?”

    • 这时你就不能用“原地置换”了。

    • 方案 A:使用 HashSet(空间 $O(n)$)。

    • 方案 B:使用二分法的思想(时间 $O(n \log n)$,空间 $O(1)$),通过统计区间内数字出现的次数来锁定重复值。

想试试看如何用“二分法”在不修改数组的情况下找出重复数字吗?我们可以接着聊聊这个思路。

正文完
 0
bdspAdmin
版权声明:本站原创文章,由 bdspAdmin 于2026-03-12发表,共计1337字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)

摆渡资源站

文章搜索
一言一句话
-「
热门文章
某个货币持仓增长了一倍,但是 jing流入没有增加多少,为啥

某个货币持仓增长了一倍,但是 jing流入没有增加多少,为啥

  这通常是因为该货币的市值(价格)上涨抵消了持仓量的增加,或者存在某些“非交易性”的变动。 简单来...
mac brew 有没有 markdown 格式化工具

mac brew 有没有 markdown 格式化工具

  在 macOS 上通过 Homebrew (brew) 安装 Markdown 格式化工具非常方...
2026比特币稳赚指南:顶级加密交易策略全揭秘!

2026比特币稳赚指南:顶级加密交易策略全揭秘!

    关键要点 定投(DCA):仍是比特币长期积累的低风险和纪律性策略。 趋势交易和波段...
使用Java类库ta4j计算基金的布林轨

使用Java类库ta4j计算基金的布林轨

ta4j简介 对于做金融分析的从业者而言,python的ta-lib是不可或缺的技术分析库,具有简单易用、功能...
全真早晚功课简介

全真早晚功课简介

         道教的斋醮仪式很多,主要的日常宗教活动是早晚功课经。凡是道教徒每天都要上殿唪诵,所...
最新评论
333985 333985 每天都在战争,希望2026和平.
最新文章
nginx中location匹配规则与proxy_pass代理转发

nginx中location匹配规则与proxy_pass代理转发

  最近使用nginx在服务器上配置,在做路径匹配时上遇到细节上的东西,在此做记录,安装请转 win...
算法practice1进阶

算法practice1进阶

  这两个方案是面试中常见的进阶考向,尤其是当面试官追加限制条件(如“不准修改原数组”)时,方案 B...
算法practice1

算法practice1

  https://github.com/CyC2018/CS-Notes/blob/master/...
胸部爱抚是件迷人的事,如果能掌握诀窍更好──5个胸部爱抚阶段的相关诀窍

胸部爱抚是件迷人的事,如果能掌握诀窍更好──5个胸部爱抚阶段的相关诀窍

  爱抚胸部绝对是性爱前戏中最常见,同时也最重要的一环。只是,大多数的男生虽然都有迷恋女生胸部的倾向...
8招舌吻技巧

8招舌吻技巧

  舌吻技巧1:先从正常的亲嘴开始 先从普通的亲嘴开始,慢慢酝酿舌吻的情绪。保持嘴唇柔软并微微张开,...