【LeetCode 熱題 100】41. 缺失的第一個正數——(解法二)原地哈希

Problem: 41. 缺失的第一個正數
題目:給你一個未排序的整數數組 nums ,請你找出其中沒有出現的最小的正整數。
請你實現時間復雜度為 O(n) 并且只使用常數級別額外空間的解決方案。

【LeetCode 熱題 100】41. 缺失的第一個正數——(解法一)暴力解

文章目錄

  • 整體思路
  • 完整代碼
  • 時空復雜度
    • 時間復雜度:O(N)
    • 空間復雜度:O(1)

整體思路

這段代碼旨在高效地解決 “缺失的第一個正數” 問題。與上一個排序解法不同,此版本采用了一種稱為 “原地哈希” (In-place Hashing)“循環排序” (Cyclic Sort) 的思想,能夠在 O(N) 的時間復雜度和 O(1) 的空間復雜度內完成任務,是此問題的最優解。

算法的核心思想是:嘗試將每個數字 x 放到它“應該”在的位置上。對于一個長度為 n 的數組,如果我們只關心 1n 的正整數,那么數字 1 應該在索引 0 的位置,數字 2 應該在索引 1 的位置,以此類推,數字 x 應該在索引 x-1 的位置。

算法的執行步驟如下:

  1. 原地重排數組

    • 算法通過一個 for 循環遍歷數組。在 for 循環的內部,是一個 while 循環,這是算法的核心。
    • 對于當前位置 i 的數字 nums[i]
      • while 循環的條件:這個條件非常關鍵,它同時檢查三件事:
        1. nums[i] >= 1 && nums[i] <= n:確保 nums[i] 是一個在 [1, n] 范圍內的有效正數。我們只關心這些數字,任何超出這個范圍的數字(負數、零、或大于 n 的數)都無需處理,因為它們不可能是 1n 范圍內的缺失正數。
        2. nums[i] != nums[nums[i] - 1]:檢查 nums[i] 是否已經在它正確的位置上。nums[i] 應該在的位置是 nums[i] - 1。如果 nums[i] 的值不等于 numsnums[i]-1 索引上的值,說明 nums[i] 還未歸位。
      • 執行交換:如果 while 條件滿足,就執行一次交換,將 nums[i]nums[nums[i] - 1] 的值互換。這個操作的目的就是將 nums[i] 送到它應該在的位置去。
    • 這個 while 循環會持續進行,直到當前 i 位置的數字不再滿足交換條件(可能因為它已經歸位,或者它是一個無效數字)。然后外層 for 循環才會進入下一個 i
  2. 查找缺失的正數

    • 當第一步的重排完成后,理想情況下,數組 nums 應該形如 [1, 2, 3, ..., n]
    • 接著,進行第二次遍歷。在這個遍歷中,檢查每個位置 i 的值是否等于 i+1
    • 如果 nums[i] != i + 1,這意味著 i+1 這個正整數本應在這里,但它不在。由于我們已經把所有能歸位的數字都歸位了,這個不在位置上的 i+1 就是我們找到的第一個缺失的正數。直接返回 i+1
  3. 處理特殊情況

    • 如果在第二次遍歷中,所有的數字都在它們正確的位置上(即 nums 就是 [1, 2, ..., n]),那么循環會正常結束。
    • 這說明 1n 所有的正數都存在,因此,缺失的第一個正數就是 n+1

完整代碼

class Solution {/*** 在一個未排序的整數數組中,找到沒有出現的最小的正整數。* 采用原地哈希/循環排序的方法。* @param nums 輸入的整數數組* @return 缺失的最小正整數*/public int firstMissingPositive(int[] nums) {int n = nums.length;// 步驟 1: 原地重排數組,嘗試將每個數字放到它正確的位置上。// 數字 x 應該在索引 x-1 的位置。for (int i = 0; i < n; i++) {// 當 nums[i] 在 [1, n] 范圍內,并且它沒有在正確的位置上時,循環交換。// 正確的位置是指:nums[i] 的值應該等于索引 nums[i]-1 上的值。// 例如,如果 nums[i] = 3,它應該在索引 2 的位置,即 nums[2] 的值應該是 3。while (nums[i] >= 1 && nums[i] <= n && nums[i] != nums[nums[i] - 1]) {// 將 nums[i] 與它目標位置上的數進行交換。int temp = nums[nums[i] - 1];nums[nums[i] - 1] = nums[i];nums[i] = temp;}}// 步驟 2: 查找第一個不滿足 nums[i] == i + 1 的位置。for (int i = 0; i < n; i++) {// 如果在索引 i 上的值不是 i+1,那么 i+1 就是第一個缺失的正數。if (nums[i] != i + 1) {return i + 1;}}// 步驟 3: 如果 1 到 n 都存在,那么缺失的第一個正數就是 n+1。return n + 1;}
}

時空復雜度

時間復雜度:O(N)

  1. forwhile 循環:雖然代碼中有一個嵌套的 while 循環,但它的總執行次數并不是 O(N^2)。
  2. 均攤分析
    • 關鍵在于,每一次 while 循環中的成功交換,都會將至少一個數字(即 nums[nums[i] - 1] 被換過來的那個)放到了它最終正確的位置上。
    • 一個數字一旦被放到正確的位置,它就不會再參與后續的交換了(因為 nums[i] == nums[nums[i] - 1] 條件會使其不滿足 while 循環)。
    • 由于數組中只有 N 個位置,最多只會發生 N 次成功的交換。
    • 因此,所有 while 循環的總執行次數(包括成功的交換和不成功的檢查)加起來是 O(N) 級別的。外層 for 循環也執行 N 次。所以這部分的復雜度是 O(N)
  3. 第二次遍歷:最后的 for 循環遍歷數組一次,時間復雜度為 O(N)

綜合分析
算法的總時間復雜度是 O(N) + O(N) = O(N)

空間復雜度:O(1)

  1. 主要存儲開銷:該算法直接在輸入數組 nums 上進行修改,沒有創建任何與輸入規模 N 成比例的新的數據結構。
  2. 輔助變量:只使用了 n, i, temp 等幾個常數級別的整型變量。

綜合分析
算法所需的額外輔助空間是常數級別的。因此,其空間復雜度為 O(1)。這是該問題最優的空間效率。

參考靈神

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87785.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87785.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87785.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#上位機之Modbus通信協議!

文章目錄前言一、Modbus概念二、使用步驟1.使用Modbus準備2.使用步驟三、Modbus RTU 與 Modbus ASCII對比前言 Modbus通信協議&#xff01; 一、Modbus概念 從站設備編碼&#xff08;從站地址、單元ID&#xff09;&#xff0c;一主多從。 存儲區&#xff1a;0-線圈狀態、1-輸…

前后端分離架構下的跨域問題與解決方案

在現代Web開發中&#xff0c;特別是隨著前后端分離架構的普及&#xff0c;跨域問題成為了開發者必須面對的一個重要議題。本文將詳細介紹什么是跨域問題、其產生的原因以及如何從前端和后端兩個角度來解決這個問題&#xff0c;并提供一些實用的代碼示例。一、跨域問題概述1. 定…

搜索數據建設系列之數據架構重構

導讀 主要概述百度搜索業務數據建設的創新實踐&#xff0c;重點圍繞寬表模型設計、計算引擎優化和新一代業務服務交付模式&#xff08;圖靈3.0開發模式&#xff09;三大方向&#xff0c;解決了傳統數倉在搜索場景下面臨的諸多挑戰&#xff0c;實現了搜索數據建設的高效、穩定、…

2025年滲透測試面試題總結-2025年HW(護網面試) 29(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。、 目錄 2025年HW(護網面試) 29 1. 樣本分析思路 2. Linux GDB分析樣本示例 3. 應急案例&#xff1a;WebShell后…

動態編程入門第二節:委托與事件 - Unity 開發者的高級回調與通信藝術

動態編程入門第一節&#xff1a;C# 反射 - Unity 開發者的超級工具箱 動態編程入門第二節&#xff1a;委托與事件 - Unity 開發者的高級回調與通信藝術 上次我們聊了 C# 反射&#xff0c;它讓程序擁有了在運行時“看清自己”的能力。但光能看清還不夠&#xff0c;我們還需要讓…

降低網絡安全中的人為風險:以人為本的路徑

有效降低網絡安全中的人為風險&#xff0c;關鍵在于采取以人為本的方法。這種方法的核心在于通過高效的培訓和實踐&#xff0c;使員工掌握安全知識、踐行安全行為&#xff0c;并最終培育出安全且相互支持的文化氛圍。 誠然&#xff0c;技術和政策必須為良好的安全行為提供支持、…

opencv裁剪和編譯

opencv裁剪和編譯 0. 準備工作 0.1 下載和安裝Eigen 地址 https://eigen.tuxfamily.org/index.php?titleMain_Page對于opencv編譯&#xff0c;需要增加EIGEN_INCLUDE_PATH和開啟WITH_EIGEN -DWITH_EIGENON -DEIGEN_INCLUDE_PATH./3rd/eigen-3.4.01. 實際腳本 編譯腳本如下: ch…

小白成長之路-mysql數據基礎(三)

文章目錄一、主從復制二、案例總結一、主從復制 1、master開啟二進制日志記錄2、slave開啟IO進程&#xff0c;從master中讀取二進制日志并寫入slave的中繼日志3、slave開啟SQL進程&#xff0c;從中繼日志中讀取二進制日志并進行重放4、最終&#xff0c;達到slave與master中數據…

通過 Windows 共享文件夾 + 手機訪問(SMB協議)如何實現

通過 Windows 共享文件夾 手機訪問&#xff08;SMB協議&#xff09; 實現 PC 和安卓手機局域網文件共享&#xff0c;具體步驟如下&#xff1a; &#x1f4cc; 前置條件 電腦和手機連接同一局域網&#xff08;同一個Wi-Fi或路由器&#xff09;。關閉防火墻或放行SMB端口&#…

【Python3教程】Python3高級篇之正則表達式

博主介紹:?全網粉絲23W+,CSDN博客專家、Java領域優質創作者,掘金/華為云/阿里云/InfoQ等平臺優質作者、專注于Java技術領域? 技術范圍:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大數據、物聯網、機器學習等設計與開發。 感興趣的可…

Redis--黑馬點評--達人探店功能實現詳解

達人探店發布探店筆記探店筆記類似于點評網站的評價&#xff0c;往往是圖文結合&#xff0c;對應的表有兩個&#xff1a;tb_blog&#xff1a;探店筆記表&#xff0c;包含筆記中的標題、文字、圖片等tb_blog_comments&#xff1a;其他用戶對探店筆記的評價tb_blog表結構如下&…

一探 3D 互動展廳的神奇構造?

3D 互動展廳的神奇之處&#xff0c;離不開一系列先進技術的強力支撐 。其中&#xff0c;VR(虛擬現實)技術無疑是核心亮點之一。通過佩戴 VR 設備&#xff0c;觀眾仿佛被瞬間 “傳送” 到一個全新的世界&#xff0c;能夠全身心地沉浸其中&#xff0c;360 度無死角地觀察周圍的一…

C++ 網絡編程(15) 利用asio協程搭建異步服務器

&#x1f680; [協程與異步服務器實戰]&#xff1a;[C20協程原理與Boost.Asio異步服務器開發] &#x1f4c5; 更新時間&#xff1a;2025年07月05日 &#x1f3f7;? 標簽&#xff1a;C20 | 協程 | Boost.Asio | 異步編程 | 網絡服務器 文章目錄前言一、什么是協程&#xff1f;二…

【Java21】在spring boot中使用虛擬線程

文章目錄 0.環境說明1.原理解析2.spring boot的方案3.注意事項&#xff08;施工中&#xff0c;歡迎補充&#xff09; 前置知識 虛擬線程VT&#xff08;Virtual Thread&#xff09; 0.環境說明 用于驗證的版本&#xff1a; spring boot: 3.3.3jdk: OpenJDK 21.0.5 spring boot…

利器:NPM和YARN及其他

文章目錄**1. 安裝 Yarn&#xff08;推薦方法&#xff09;****2. 驗證安裝****3. 常見問題及解決方法****① 權限不足&#xff08;Error: EPERM&#xff09;****② 網絡問題&#xff08;連接超時或下載失敗&#xff09;****③ 環境變量未正確配置****4. 替代安裝方法&#xff0…

跨平臺直播美顏SDK集成實錄:Android/iOS如何適配貼紙功能

眾所周知&#xff0c;直播平臺與短視頻平臺的貼紙功能不僅是用戶表達個性的方式&#xff0c;更是平臺提高用戶粘性和互動轉化的法寶。 可問題來了&#xff1a;如何讓一個貼紙功能&#xff0c;在Android和iOS兩大平臺上表現一致、運行流暢、加載穩定&#xff1f;這背后&#xff…

JavaWeb(蒼穹外賣)--學習筆記04(前端:HTML,CSS,JavaScript)

前言 本片文章是學習B站黑馬程序員蒼穹外賣的學習筆記。因為最近期末周&#xff0c;一直在應付考試所以就學的很少&#xff0c;恰好視頻中在講Nginx反向代理和負載均衡&#xff08;寫著對前端的內容做一個復習&#xff09; 概述&#xff1a; 1.web前端主要由三部分組成&…

智能學號抽取系統 V5.4.3.2 —— Vue.js 實現的多功能課堂隨機抽簽工具

智能學號抽取系統 V5.4.3.2 —— Vue.js 實現的多功能課堂隨機抽簽工具 在教學或會議場景中&#xff0c;我們經常需要隨機抽取一個或多個學號/編號來決定發言者、答題者或者參與者。為了提高效率和公平性&#xff0c;我們可以使用一些智能化的小工具來實現這一過程。 今天介紹…

從0開始學習R語言--Day39--Spearman 秩相關

在非參數統計中&#xff0c;不看數據的實際數值&#xff0c;單純比較兩組變量的值的排名是通用的基本方法&#xff0c;但在客觀數據中&#xff0c;很多變量的關系都是非線性的&#xff0c;其他的方法不是對樣本數據的大小和線性有要求&#xff0c;就是只能對比數據的差異性&…

WSL - Linux 安裝 Anaconda3-2025.06-0 詳細教程 [WSL 分發版均適用]

一、檢查系統狀態 安裝前先確認 WSL - Linxu 已正常啟動&#xff08;比如 Ubuntu&#xff09;&#xff0c;網絡連接穩定&#xff0c;并且系統磁盤有足夠空間&#xff0c;一般建議預留至少 5GB 以上的可用空間&#xff0c;避免因空間不足導致安裝失敗。 二、下載安裝包 Anacond…