【Leetcode刷題隨筆】01. 兩數之和

1. 題目描述

給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和為目標值的那 兩個 整數,并返回他們的數組下標。

你可以假設每種輸入只會對應一個答案。但是,數組中同一個元素不能使用兩遍。

示例:

給定 nums = [2, 7, 11, 15], target = 9

因為 nums[0] + nums[1] = 2 + 7 = 9

所以返回 [0, 1]

2. 解法分析

2.1 解法1:雙循環

容易想到使用雙層for循環來枚舉答案的暴力方法解決此問題,但是效率太低下,O(n2)時間復雜度,不適合大數據量

該方法過程如下:

  1. 構建循環
  • 外層循環變量i從0到numsSize-1

  • 內層循環變量ji+1numsSize-1(確保不會重復使用同一個元素)

  1. 檢查數對和:

if(nums[i] + nums[j] == target)
  • 如果找到滿足條件的數對,執行以下操作:

  • 設置返回大小*returnSize = 2

  • 動態分配結果數組(兩個int)

  • 將兩個索引存入數組:result[0]=i, result[1]=j

  • 直接返回結果數組

  1. 未找到解的處理:
  • 設置*returnSize = 0

  • 返回NULL

時間復雜度

  • O(n2): 最壞情況下需要檢查所有n(n-1)/2個數對

空間復雜度

  • O(1): 除結果數組外只使用常數空間(結果數組不計入空間復雜度時)
  1. 無解處理:
  • 設置*returnSize=0并返回NULL是標準做法

  • 調用者可通過returnSize判斷是否有解

示例執行過程

輸入:nums = [2,7,11,15], target=9

  1. i=0 (值2), j=1 (值7): 2+7=9 → 找到解

  2. 分配結果數組,設置result[0]=0, result[1]=1

  3. 設置*returnSize=2

  4. 返回結果數組[0,1]

2.2 解法二:哈希表

當我們需要查詢一個元素是否出現過,或者一個元素是否在集合里的時候,就要第一時間想到哈希法。我們首先將所有元素遍歷一遍存放到哈希表中,第二次遍歷的時候就去哈希表中查詢是否有已經遍歷過的數和當前遍歷的數相加是否等于target。

哈希表版本解題思路:

步驟1:定義哈希表結構

  • 使用結構體map構造哈希表的條目,包含:

      key: 數組元素的值value: 該元素在數組中的索引
    

步驟2:實現哈希表基本操作

  • hashMapAdd: 添加或更新鍵值對。如果鍵不存在,創建新條目并添加到哈希表;如果存在,則更新其值。

  • hashMapFind: 根據鍵查找條目,返回條目指針(找不到返回NULL)。

  • hashMapCleanUp: 清理哈希表,釋放所有條目內存。

步驟3:實現twoSum函數

a. 初始化全局哈希表指針為NULL(避免之前的數據干擾)。

b. 預分配結果數組ans(兩個整數)。

c. 第一次遍歷數組:將每個元素的值作為key,索引作為value存入哈希表。

注意:如果遇到相同的元素,后面的索引會覆蓋前面的(因為同一個key在哈希表中只能存在一個)。

d. 第二次遍歷數組:對于每個元素nums[i],計算補數complement = target - nums[i],然后在哈希表中查找補數。

查找成功且滿足條件(補數對應的索引不等于當前索引,避免同一個元素用兩次)時:

將當前索引i和補數的索引hashMapRes->value存入結果數組。

設置返回數組大小為2,返回結果數組。

e. 如果遍歷結束未找到,則清理哈希表并返回NULL。

優勢:
哈希表版本的核心思路是“空間換時間”,通過O(n)的額外空間將時間復雜度從O(n2)降低到O(n)。它通過兩次遍歷完成:

第一次遍歷:建立值到索引的映射(哈希表)。

第二次遍歷:對于每個元素,檢查其補數是否在哈希表中(且不是自身)。

與雙層循環法相比,哈希表法更適合處理大規模數據,但需要注意內存泄漏和線程安全問題。

3. C語言代碼實現

3.1 雙層for循環法

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {for(int i = 0; i < numsSize; i++){for(int j = i + 1; j < numsSize; j++){if(nums[i] + nums[j] == target){*returnSize = 2;int* result = (int*)malloc(2 * sizeof(int));result[0] = i;result[1] = j;return result;}}}*returnSize = 0;return NULL;
}

3.2 哈希表法

typedef struct
{int key;int value;UT_hash_handle hh;
}map;map* hashMap = NULL;void hashMapAdd(int key, int value){map* s;//檢查key是否在hash表中HASH_FIND_INT(hashMap, &key, s);if(s == NULL){s = (map*)malloc(sizeof(map));s->key = key;HASH_ADD_INT(hashMap, key, s);}s->value = value;
}map* hashMapFind(int key){map* s;HASH_FIND_INT(hashMap, &key, s);return s;
}void hashMapCleanUp(){map* cur, *tmp;HASH_ITER(hh, hashMap, cur, tmp){HASH_DEL(hashMap, cur);free(cur);}
}void hashPrint(){map* s;for(s = hashMap; s != NULL; s = (map*)(s -> hh.next)){printf("key = %d, value = %d", s->key, s->value);}
}int* twoSum(int* nums, int numsSize, int target, int* returnSize){int i, *ans;//在哈希表里尋找補數map* hashMapRes;hashMap = NULL;ans = malloc(sizeof(int) * 2);for(i = 0; i < numsSize; i++){//key代表nums[i]的值,value代表所在indexhashMapAdd(nums[i], i);}for(i = 0; i < numsSize; i++){hashMapRes = hashMapFind(target - nums[i]);if(hashMapRes && hashMapRes -> value != i){ans[0] = i;ans[1] = hashMapRes -> value;*returnSize = 2;return ans;}}hashMapCleanUp();return NULL;
}

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

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

相關文章

【機器學習深度學習】多層神經網絡的構成

目錄 一、神經網絡模型的結構化組成方式 1. 最底層&#xff1a;神經網絡模型 (Model) 2. 中間層&#xff1a;單個神經網絡層 (Layer) 3. 最頂層&#xff1a;訓練參數的細節 (Parameters & Variables) 二、關鍵理解要點 三、類比理解 場景一&#xff1a;工廠運作 場…

設計模式:揭秘Java原型模式——讓復雜對象的創建不再復雜

原型模式 原型模式介紹 定義: 原型模式(Prototype Design Pattern)用一個已經創建的實例作為原型&#xff0c;通過復制該原型對象來創建一個和原型對象相同的新對象。 西游記中的孫悟空&#xff0c;拔毛變小猴&#xff0c;孫悟空這種根據自己的形狀復制出多個身外化身的技巧&…

Go語言-文件操作

基本介紹 文件是數據源&#xff0c;數據庫也是一種特殊的文件。 Go語言中os.File結構體封裝了文件的相關操作。 打開和關閉文件 -----打開文件----- file, err : os.Open("D:/111.txt") if err ! nil{fmt.Println("err ", err) }此時file就是一個指針&…

【電力物聯網】云–邊協同介紹

(??? )&#xff0c;Hello&#xff0c;我是祐言QAQ我的博客主頁&#xff1a;C/C語言&#xff0c;數據結構&#xff0c;Linux基礎&#xff0c;ARM開發板&#xff0c;網絡編程等領域UP&#x1f30d;快上&#x1f698;&#xff0c;一起學習&#xff0c;讓我們成為一個強大的技術…

《深入解析 C#(第 4 版)》推薦

《深入解析 C#&#xff08;第 4 版&#xff09;》推薦 在 C# 語言不斷演進的技術浪潮中&#xff0c;《深入解析 C#&#xff08;第 4 版&#xff09;》猶如一座燈塔&#xff0c;為開發者照亮探索的道路。無論是經驗豐富的老程序員&#xff0c;還是初入 C# 領域的新手&#xff0c…

【網絡】Linux 內核優化實戰 - net.core.netdev_max_backlog

目錄 Linux 內核參數 net.core.netdev_max_backlog 詳解一、參數概述二、參數功能與作用2.1 核心功能2.2 網絡數據包處理流程 三、查看當前參數值3.1 通過 sysctl 命令3.2 直接讀取 /proc/sys 文件 四、修改參數值4.1 臨時修改&#xff08;立即生效&#xff0c;重啟后失效&…

Nuitka 打包Python程序

文章目錄 Nuitka 打包Python程序&#x1f680; **一、Nuitka 核心優勢**?? **二、環境準備&#xff08;Windows 示例&#xff09;**&#x1f4e6; **三、基礎打包命令****單文件腳本打包****帶第三方庫的項目** &#x1f6e0;? **四、高級配置選項****示例&#xff1a;完整命…

自動獲取文件的內存大小怎么設置?批量獲取文件名和內存大小到Excel中的方法

在對重要數據進行備份或遷移操作前&#xff0c;為確保備份全面無遺漏&#xff0c;且合理規劃目標存儲設備的空間&#xff0c;會將文件名和內存提取到 Excel。比如&#xff0c;某個部門要將舊電腦中的文件遷移到新服務器&#xff0c;提前整理文件信息&#xff0c;能清晰知道所需…

創建型設計模式——單例模式

單例設計模式 什么是創建型設計模式有哪些創建型設計模式 單例設計模式實現方法餓漢式單例懶漢式單例實現方法 CSDN——C單例模式詳解 單例設計模式是一種創建型設計模式 什么是創建型設計模式 創建型設計模式&#xff0c;就是通過控制對象的創建方式來解決設計問題。 有哪…

html 照片環 - 圖片的動態3D環繞

html 照片環 - 圖片的動態3D環繞 引言一、源碼二、圖轉base64參考鏈接 引言 效果展示&#xff1a; 一、源碼 原始圖片的base64編碼字符太多了&#xff0c;博客放不下&#xff0c;將圖片縮小后的加入html的源碼如下&#xff1a; <!DOCTYPE html> <html><hea…

ADIOS2 介紹與使用指南

文章目錄 ADIOS2 介紹與使用指南什么是ADIOS2?ADIOS2 的主要特點ADIOS2 核心概念ADIOS2 安裝Linux 系統安裝Windows 安裝 ADIOS2 基本使用C 示例Python 示例 ADIOS2 高級特性并行I/O流模式 ADIOS2 引擎類型性能優化建議總結 ADIOS2 介紹與使用指南 什么是ADIOS2? ADIOS2(Ad…

網絡安全 vs 信息安全的本質解析:數據盾牌與網絡防線的辯證關系關系

在數字化生存的今天&#xff0c;每一次手機支付、每一份云端文檔、每一條醫療記錄的背后&#xff0c;都矗立著這兩座安全堡壘。理解它們的協同邏輯&#xff0c;不僅是技術從業者的必修課&#xff0c;更是企業構建數字防護體系的底層認知 —— 畢竟當勒索軟件同時切斷 "護城…

ping-pong操作

常見不匹配的原因 瞬時數據率的差異&#xff1b; 數據順序的差異&#xff1b; 對比維度PipelineFIFOPing-Pong邏輯復制結構類型時序分級推進&#xff08;寄存器鏈&#xff09;環形隊列&#xff08;緩沖區&#xff09;雙緩沖區&#xff08;輪換使用&#xff09;功能塊并行&am…

21.合并兩個有序鏈表

將兩個升序鏈表合并為一個新的 升序 鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。 思路&#xff1a;這里使用的主要數據結構是單鏈表。該算法采用經典的雙指針技術來合并列表。 A dummy node is created; this node does not hold any meaningful value b…

vue3中簡單易懂說明nextTick的使用

nextTick(): 等待下一次 DOM 更新刷新的工具方法 重點解釋: 當你在 Vue 中更改響應式狀態時&#xff0c;最終的 DOM 更新并不是同步生效的&#xff0c;而是由 Vue 將它們緩存在一個隊列中&#xff0c;直到下一個“tick”才一起執行。這樣是為了確保每個組件無論發生多少狀態改變…

gRPC 相關介紹

介紹 依賴兩大技術 HTTP/2 作為傳輸協議 gRPC 底層用 HTTP/2&#xff0c;它支持&#xff1a; 多路復用&#xff08;在一條 TCP 連接中并行傳輸多個請求和響應&#xff09;二進制傳輸&#xff08;更緊湊、高效&#xff09;流式傳輸&#xff08;客戶端流、服務端流、雙向流&…

PyTorch 模型鏡像下載與安裝指南

在國內&#xff0c;由于網絡限制&#xff0c;直接從 PyTorch 官方源下載可能會遇到速度慢或無法訪問的問題。為了解決這一問題&#xff0c;可以使用國內鏡像源來加速下載和安裝 PyTorch。 文章目錄 安裝指定版本的 PyTorch&#xff08;以 CUDA 11.8 為例&#xff09;安裝 CPU 版…

2025年SVN學習價值分析

?? 一、SVN的現狀與應用場景分析 仍在特定領域發揮作用 傳統企業維護場景&#xff1a;在金融、電信、政府等采用集中式開發流程的機構中&#xff0c;許多遺留系統仍使用SVN管理。這些系統往往體量龐大、架構穩定&#xff0c;遷移成本高&#xff0c;因此SVN短期內不會被完全替…

JavaScript中的10種排序算法:從入門到精通

作為前端開發者&#xff0c;排序算法是我們必須掌握的基礎知識。無論是在面試中&#xff0c;還是在實際開發中處理數據展示時&#xff0c;排序都是一個常見需求。今天&#xff0c;我將用通俗易懂的方式&#xff0c;帶你了解JavaScript中最常見的10種排序算法。 1. 冒泡排序 - …

【微信小程序】6、SpringBoot整合WxJava獲取用戶手機號

1、手機號快速驗證組件 手機號快速驗證組件 旨在幫助開發者向用戶發起手機號申請&#xff0c;并且必須經過用戶同意后&#xff0c;開發者才可獲得由平臺驗證后的手機號&#xff0c;進而為用戶提供相應服務。 該能力與手機號實時驗證組件的區別為&#xff1a; 手機號快速驗證…