面試必刷的數組三連:原地刪除與合并

堅持用 清晰易懂的圖解 + 多語言代碼,讓每道題變得簡單!
呆頭個人主頁詳情
呆頭個人Gitee代碼倉庫
呆頭詳細專欄系列
座右銘: “不患無位,患所以立。”
在這里插入圖片描述

面試必刷的數組三連:原地刪除與合并

  • 前言
  • 目錄
  • 1.移除元素
  • 2.刪除有序數組中的重復項
      • 關鍵點
      • 詳細步驟(以 `nums = [1, 1, 2, 2, 3]` 為例)
      • 為什么 `nums[i] == nums[k]` 時,`k` 不移動?
      • 總結
  • 3.合并兩個有序數組
      • 解決思路
      • 解決代碼
      • 代碼解釋
      • 示例
      • 復雜度分析


前言

🚀 你好,歡迎來到《編程闖關記》!
這里是算法與數據結構的實戰基地,也是你從“暴力解法”到“最優解”的進化場。

🔍 專欄初衷

  • 清晰的圖解 + 多語言代碼(Python/Java/C++/C),拆解每道題背后的邏輯。
  • 不只講“怎么做”,更講“為什么”——從題目分析、邊界條件到復雜度優化。
  • 適合想夯實基礎突擊面試的你,尤其針對LeetCode/牛客高頻題!

💡 如何使用本專欄
1?? 先獨立思考:嘗試自己寫出第一版代碼(哪怕很爛)。
2?? 對比解法:看看我的思路和你的差異,吸收優化技巧。
3?? 舉一反三:每篇末尾會附相似題目鏈接,趁熱打鐵。

📌 堅持打卡
算法沒有捷徑,但正確的方法能讓你少走彎路。每天15分鐘,和我一起用代碼雕刻思維!

(正文開始👇)


目錄

1.移除元素

力扣鏈接直達<請點擊
在這里插入圖片描述
在這里插入圖片描述

int removeElement(int* nums, int numsSize, int val) 
{int count = 0;for(int i=0;i<numsSize;i++){if(nums[i]!=val){nums[count] = nums[i];count++;}}return count;
}

代碼說明:

  • 初始化計數count: count從0開始,用于記錄不等于val的元素數量,并作為新數組的索引。

  • **遍歷數組:**使用i遍歷整個數組,檢查每個元素是否等于val。

  • 如果nums[i]不等于val,則將其復制到nums[k]的位置,并遞增k。

  • 如果等于val,則跳過該元素。

  • 返回結果:最終k即為新數組的長度,且數組的前k個元素均為不等于val的元素。

這種方法高效且滿足題目要求的原地修改條件。
在這里插入圖片描述

2.刪除有序數組中的重復項

力扣鏈接直達<請點擊
在這里插入圖片描述
在這里插入圖片描述

int removeDuplicates(int* nums, int numsSize) {if (numsSize == 0) return 0; // 空數組直接返回 0int k = 0; // 慢指針,初始指向第一個元素for (int i = 1; i < numsSize; i++) {if (nums[i] != nums[k]) { // 發現新元素k++; // 移動慢指針nums[k] = nums[i]; // 存入新元素}// 如果 nums[i] == nums[k],跳過(i 繼續前進)}return k + 1; // 返回去重后的長度
}

在這里插入圖片描述

“原地移除重復元素” 的算法中,當遇到重復元素時,并不是真的刪除它,而是通過 覆蓋(跳過) 的方式,讓后面的非重復元素占據前面的位置,最終只保留不重復的部分。

關鍵點

  1. 不真正刪除元素:數組在內存中是連續的,不能直接刪除某個元素,只能覆蓋。
  2. 雙指針策略
    • 慢指針 k:記錄 不重復元素應該存放的位置
    • 快指針 i:遍歷數組,檢查是否有新元素。
  3. 覆蓋重復元素
    • 如果 nums[i] 是新元素(即 nums[i] != nums[k]),就把它存到 nums[k+1],然后 k++
    • 如果 nums[i] 是重復的(即 nums[i] == nums[k]),就 跳過它i 繼續前進,k 不動)。

詳細步驟(以 nums = [1, 1, 2, 2, 3] 為例)

iknums[i]nums[k]操作nums 變化
1011nums[i] == nums[k],跳過[1, 1, 2, 2, 3](不變)
2021nums[i] != nums[k],存入 nums[1] = 2k++[1, 2, 2, 2, 3]
3122nums[i] == nums[k],跳過[1, 2, 2, 2, 3](不變)
4132nums[i] != nums[k],存入 nums[2] = 3k++[1, 2, 3, 2, 3]

最終結果

  • k+1 = 3 個元素是去重后的:[1, 2, 3](后面的 2, 3 可以忽略)。
  • 返回 k + 1 = 3(去重后的長度)。

為什么 nums[i] == nums[k] 時,k 不移動?

  • k 指向的是當前不重復部分的最后一個元素
  • 如果 nums[i]nums[k] 相同,說明 nums[i] 是重復的,直接跳過(不存入數組)。
  • 只有遇到新元素時,才存入 nums[k+1] 并移動 k

總結

  • 移除重復元素 實際上是 用后面的不重復元素覆蓋前面的重復位置
  • k 的作用
    • 記錄 去重后的數組末尾位置
    • 只有遇到新元素時才移動 k,否則跳過。
  • 時間復雜度 O(n),空間復雜度 O(1)(原地修改)。

這樣,最終 nums 的前 k+1 個元素就是去重后的結果,而后面部分可以忽略。

3.合并兩個有序數組

力扣鏈接直達<請點擊
在這里插入圖片描述

解決思路

由于 nums1 有足夠的空間容納 nums2 的元素,我們可以利用 雙指針 的方法從后向前合并,以避免覆蓋 nums1 中還未處理的元素。具體步驟如下:

  1. 初始化指針

    • i 指向 nums1 的最后一個有效元素(即 m - 1)。
    • j 指向 nums2 的最后一個元素(即 n - 1)。
    • k 指向 nums1 的最后一個位置(即 m + n - 1)。
  2. 從后向前比較并合并

    • 比較 nums1[i]nums2[j],將較大的元素放到 nums1[k]
    • 移動相應的指針(ij)和 k
  3. 處理剩余元素

    • 如果 nums2 中還有剩余元素(即 j >= 0),直接復制到 nums1 的前面。

解決代碼

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int i = m - 1;      // nums1 的最后一個有效元素int j = n - 1;      // nums2 的最后一個元素int k = m + n - 1;  // nums1 的最后一個位置// 從后向前合并while (i >= 0 && j >= 0) {if (nums1[i] > nums2[j]) {nums1[k--] = nums1[i--];} else {nums1[k--] = nums2[j--];}}// 如果 nums2 還有剩余元素,直接復制到 nums1 的前面while (j >= 0) {nums1[k--] = nums2[j--];}
}

在這里插入圖片描述

代碼解釋

  1. 初始化指針

    • inums1 的有效末尾開始。
    • jnums2 的末尾開始。
    • knums1 的最后一個位置開始。
  2. 比較并合并

    • 比較 nums1[i]nums2[j],將較大的元素放入 nums1[k],并移動相應的指針。
    • 這樣確保 nums1 的后半部分不會被覆蓋,直到所有元素正確歸位。
  3. 處理剩余元素

    • 如果 nums2 中還有元素未合并(即 j >= 0),直接復制到 nums1 的前面,因為 nums1 的前面部分已經處理完畢。

示例

輸入

nums1 = [1, 2, 3, 0, 0, 0], m = 3
nums2 = [2, 5, 6], n = 3

執行過程

  1. i = 2, j = 2, k = 5
    • nums1[2] = 3 < nums2[2] = 6nums1[5] = 6, j--, k--
  2. i = 2, j = 1, k = 4
    • nums1[2] = 3 < nums2[1] = 5nums1[4] = 5, j--, k--
  3. i = 2, j = 0, k = 3
    • nums1[2] = 3 > nums2[0] = 2nums1[3] = 3, i--, k--
  4. i = 1, j = 0, k = 2
    • nums1[1] = 2 == nums2[0] = 2nums1[2] = 2, j--, k--
  5. j = -1,循環結束。
  6. nums2 已無剩余元素,合并完成。

最終結果

nums1 = [1, 2, 2, 3, 5, 6]

復雜度分析

  • 時間復雜度:O(m + n),每個元素最多被比較一次。
  • 空間復雜度:O(1),沒有使用額外空間,原地修改 nums1

這種方法高效且避免了不必要的元素移動,是最優解。

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

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

相關文章

力扣經典算法篇-41-旋轉圖像(輔助數組法,原地旋轉法)

1、題干 給定一個 n n 的二維矩陣 matrix 表示一個圖像。請你將圖像順時針旋轉 90 度。 你必須在 原地 旋轉圖像&#xff0c;這意味著你需要直接修改輸入的二維矩陣。請不要 使用另一個矩陣來旋轉圖像。 示例 1&#xff1a;輸入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]]…

譯|用戶增長策略如何使用因果機器學習的案例

來自上傳文件中的文章《[Causal Machine Learning for Growth: Loyalty Programs, LTV, and What to Do When You Can’t Experiment | by Torty Sivill | Towards AI]》 本文探討了當 A/B 測試不可行時&#xff0c;如何利用因果推斷從歷史數據中獲取洞察。技術亮點在于通過構建…

java~final關鍵字

final關鍵字final基本介紹final的使用細節final基本介紹 final是最終的意思&#xff0c;可以修飾類&#xff0c;屬性&#xff0c;方法&#xff0c;局部變量什么時候會要使用到final呢&#xff1f; 1.想要類不被繼承時 2.不希望類的某個屬性的值被改變時 3.不想父類的某個方法被…

Node.js(四)之數據庫與身份認證

數據庫與身份認證 目錄 數據庫與身份認證 十三、數據庫的基本概念 13.1 什么是數據庫 13.2 常見的數據庫及分類 13.3 傳統型數據庫的數據組織結構 1. Excel 的數據組織結構 2. 傳統型數據庫的數據組織結構 3. 實際開發中庫、表、行、字段的關系 十四、安裝并配置MySQ…

SpringBoot+SpringMVC常用注解

文章目錄發展歷程項目創建項目結構入門案例配置文件的兩種方式&#xff1a;只能使用一種創建項目二入門案例常用知識及注解Controller:類上面加&#xff0c;SpringMVC的注解GetMapping:方法上面加Spring框架的兩項核心功能Component:組件。控制反轉&#xff0c;加在業務類上面&…

標準GS相位恢復算法

標準GS相位恢復算法詳解與MATLAB實現 Gerchberg-Saxton (GS) 算法是一種經典的相位恢復方法&#xff0c;廣泛應用于光學成像、衍射成像和全息技術等領域。該算法通過迭代過程從未知相位的強度測量中恢復相位信息。 算法原理 GS算法的核心思想是利用傅里葉變換關系在空間域和頻率…

【Linux網絡編程基礎--socket地址API】

一、主機字節序和網絡字節序主機字節序&#xff08;Host Byte Order&#xff09;&#xff1a;你當前電腦的內存字節順序&#xff08;比如 x86 是小端&#xff09;網絡字節序&#xff08;Network Byte Order&#xff09;&#xff1a;統一規定為大端序&#xff08;高位字節在高位…

Linux路徑MTU發現(Path MTU Discovery, PMTU)

Linux路徑MTU發現&#xff08;Path MTU Discovery, PMTU&#xff09;機制是TCP/IP協議棧中確保數據包高效傳輸的核心技術。其核心目標是動態探測源主機到目的主機路徑上的最小MTU&#xff08;Maximum Transmission Unit&#xff09;&#xff0c;從而避免IP分片&#xff0c;提升…

【MySQL進階】------MySQL程序

MySQL程序簡介 MySQL安裝完成通常會包含如下程序&#xff1a; Linux系統程序?般在 /usr/bin?錄下&#xff0c;可以通過命令查看&#xff1a; windows系統?錄&#xff1a;你的安裝路徑\MySQL Server 8.0\bin&#xff0c;可以通過命令查看&#xff1a; 每個 MySQL 程序都有許…

Linux大頁內存導致服務內存不足

Linux大頁內存導致服務內存不足的解決方法 大頁內存&#xff08;Huge Pages&#xff09;是Linux內核提供的一種機制&#xff0c;用于減少TLB&#xff08;轉換后備緩沖區&#xff09;的壓力&#xff0c;提高內存訪問性能。然而&#xff0c;如果配置不當&#xff0c;大頁內存可能…

超寬帶測距+測角+無線通信一體化模組:智能門鎖、智能遙控器、AR頭戴、智能穿戴

超寬帶測距測角無線通信一體化模組&#xff1a;智能門鎖、智能遙控器、AR頭戴、智能穿戴UWB測距測角技術&#xff0c;因其高精度、低延遲、抗干擾能力&#xff0c;正廣泛應用于“人-物-設備”的空間感知場景&#xff0c;成為構建智能空間和精準互動的重要底層技術。代表廠商與產…

基于單片機空氣質量檢測/氣體檢測系統

傳送門 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目速選一覽表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目功能速覽 概述 隨著環境污染問題日益嚴重&#xff0c;空氣質量監測成為社會關注的焦點。基于單片機的空氣質量檢…

網絡安全 | 從 0 到 1 了解 WAF:Web 應用防火墻到底是什么?

&#x1f914; 寫在前面 2020年 我參加公司的安全技能大賽&#xff0c;隊友在實操環節啟用了 WAF 防火墻&#xff0c;這是我第一次接觸到 Web 應用防火墻。作為一個 Web 開發老鳥&#xff0c;真是羞愧呀&#x1f602;。 &#x1f510; Web應用防火墻 WAF 全稱是 Web Applica…

服務器突然之間特別卡,什么原因?

原因總結&#xff1a;1.一般是本地網速的問題&#xff0c;服務器網速的問題&#xff0c;服務器CPU被占滿的問題今天發現另一個會導致特別卡的問題&#xff0c;是主存占滿也會導致卡頓。解釋如下&#xff1a;當服務器的主存&#xff08;物理內存&#xff09;被完全占滿時&#x…

AI應用標準詳解:A2A MCP AG-UI

"OpenAI接入MCP&#xff0c;Google推出A2A&#xff0c;微軟與OpenAI緊密綁定"標志著云計算競爭焦點已從"算力"和"模型參數"轉向?Agent標準協議控制權?。在AI快速演進的今天&#xff0c;我們不再僅關注單個AI的智能水平&#xff0c;而是探索多個…

Web安全學習步驟

以下是Web安全專項學習步驟&#xff0c;聚焦實戰能力培養&#xff0c;分為4個階段資源清單**&#xff0c;適合從入門到進階。重點培養漏洞挖掘能力與防御方案設計雙重視角&#xff1a;---階段1&#xff1a;Web技術筑基&#xff08;1-2個月&#xff09; | 領域 | 關鍵…

Android工程命令行打包并自動生成簽名Apk

1.進入工程目錄查看所有gradle任務 2.打包debug與release 打包前先生成jks簽名文件test.jks 在工程的build.gradle中添加簽名配置 signingConfigs {release {storeFile file("/home/dev/test.jks")storePassword "111111"keyAlias "key0"keyPas…

分布式微服務--Nacos作為配置中心(一)

1.Nacos配置遠程配置中心注意總結&#xff1a;本地配置文件必須使用 bootstrap.yml 或 bootstrap.properties遠程配置的加載優先于 application.yml&#xff0c;因此必須寫在 bootstrap 配置文件中。本地配置文件中 file-extension 的取值僅支持兩種&#xff1a;properties 或 …

Linux安裝MySQL及鏈接第三方工具詳細教程,帶圖帶錯誤分析

本教程所有代碼均為root用戶權限下操作&#xff0c;如果不是root用戶&#xff0c;在代碼前加上&#xff08;sudo &#xff09;即可 一、安裝MySQL服務 準備工作&#xff1a; 有時&#xff0c;系統無法解析 部分域名&#xff0c;導致無法獲取鏡像列表&#xff0c;從而無法安裝…

WPS2024 軟件下載及安裝教程!

軟件介紹 WPS Office是一套辦公軟件套裝&#xff0c;包含WPS文字、WPS表格、WPS演示三大功能模塊&#xff0c;可以滿足常用文字處理、表格編輯和演示制作等多種辦公需求&#xff0c;以其強大的功能和用戶友好的界面贏得了眾多用戶的青睞。 軟件&#xff1a;??????WPS Of…