三數之和:經典問題的多種優化策略

三數之和:經典問題的多種優化策略

大家好,我是Echo_Wish。今天我們來聊一個經典的算法問題——三數之和(3Sum)。它是許多面試和算法競賽中常見的問題之一,也常常考察我們對算法優化的理解和技巧。我們不僅要解決問題,還要思考如何通過優化提高算法的效率。今天的文章將帶你深入解析這個問題,并通過不同的優化策略來提高性能。

一、問題定義

三數之和的題目描述很簡單:給定一個整數數組 nums,我們需要找到所有和為零的三元組,并返回這些三元組。三元組中的元素可以是重復的,但是每個三元組中的元素順序是無關的(即 [a, b, c][c, b, a] 被認為是相同的三元組)。

比如,輸入數組是 [-1, 0, 1, 2, -1, -4],我們的任務就是找到所有三元組,使得它們的和為零,答案應該是:

[[-1, -1, 2], [-1, 0, 1]]
二、暴力解法

在剛接觸這個問題時,我們可能會想到暴力解法。最直觀的思路是使用三重循環,枚舉所有可能的三元組,判斷其和是否為零。這種方法的時間復雜度是 O(n3),顯然當數據量大時,效率不高。

def three_sum(nums):res = []n = len(nums)for i in range(n):for j in range(i + 1, n):for k in range(j + 1, n):if nums[i] + nums[j] + nums[k] == 0:res.append([nums[i], nums[j], nums[k]])return res

這種方法能夠找到所有的解,但時間復雜度太高,尤其是在面對大規模數據時,效率非常低下。

三、雙指針優化

為了優化暴力解法,我們可以考慮通過排序和雙指針來提高效率。具體做法是:首先將數組進行排序,然后固定一個元素,通過雙指針遍歷剩下的元素,尋找兩個數和為 -nums[i] 的情況。這種方法的時間復雜度降低到 O(n2)

具體步驟如下:

  1. 排序:首先對數組進行排序,這樣可以方便地用雙指針查找和為零的三元組。
  2. 固定一個元素:我們通過固定第一個元素,然后在剩下的部分使用雙指針查找另外兩個數。
  3. 雙指針遍歷:在剩下的部分,我們使用左右兩個指針分別從兩端開始向中間移動。根據當前的和調整指針的位置,確保查找所有滿足條件的三元組。

以下是代碼實現:

def three_sum(nums):nums.sort()  # 排序res = []n = len(nums)for i in range(n):if i > 0 and nums[i] == nums[i - 1]:  # 跳過重復元素continueleft, right = i + 1, n - 1  # 雙指針while left < right:total = nums[i] + nums[left] + nums[right]if total == 0:res.append([nums[i], nums[left], nums[right]])left += 1right -= 1# 跳過重復的元素while left < right and nums[left] == nums[left - 1]:left += 1while left < right and nums[right] == nums[right + 1]:right -= 1elif total < 0:left += 1else:right -= 1return res

在這個優化版的解法中,我們通過排序減少了重復檢查的機會,并且雙指針有效地縮小了搜索范圍,將時間復雜度降低為 O(n2),顯著提升了性能。

四、進一步優化:跳過不必要的計算

雖然雙指針方法已經足夠優化了,但我們依然可以進一步減少不必要的計算。特別是,在某些情況下,數組中的某些元素根本不可能構成有效的三元組,因此可以提前跳過這些元素。例如,若某個元素大于零,那么它與剩余的元素無法構成和為零的三元組,可以直接終止計算。

讓我們來看看如何實現這個優化:

def three_sum(nums):nums.sort()res = []n = len(nums)for i in range(n):if nums[i] > 0:  # 如果當前元素大于零,則不可能形成和為零的三元組breakif i > 0 and nums[i] == nums[i - 1]:  # 跳過重復元素continueleft, right = i + 1, n - 1while left < right:total = nums[i] + nums[left] + nums[right]if total == 0:res.append([nums[i], nums[left], nums[right]])left += 1right -= 1while left < right and nums[left] == nums[left - 1]:left += 1while left < right and nums[right] == nums[right + 1]:right -= 1elif total < 0:left += 1else:right -= 1return res

在這個版本中,我們增加了一個判斷條件:如果當前元素大于零,則跳出循環,因為此時已經無法組成和為零的三元組。

五、總結與展望

在解決三數之和問題時,最直接的暴力解法雖然簡單易懂,但并不高效,尤其是在面對大規模數據時。通過引入排序和雙指針技術,我們將時間復雜度降低到了 O(n2),這對于大多數實際應用來說已經足夠高效。同時,針對不必要的計算和重復元素的跳過,也進一步優化了算法的性能。

三數之和是一個典型的面試題,掌握其基本思路和優化方法不僅有助于提高解決問題的效率,也能夠幫助我們在算法設計中學會如何通過優化減少時間復雜度,提高程序的執行效率。希望通過本文的分析和優化策略,能夠幫助你更好地理解并解決這個經典問題。

如果你對三數之和或其他算法問題有任何想法或疑問,歡迎在評論中與我討論!

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

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

相關文章

Go 語言中的協程

概念 Go語言中的協程&#xff08;Goroutine&#xff09;是一種由Go運行時管理的輕量級線程。它是Go語言并發模型的核心&#xff0c;旨在通過簡單、易用的方式支持高并發的程序設計。 創建協程 協程的創建非常簡單&#xff0c;只需要使用go關鍵字&#xff0c;后面跟著一個函數…

JAVA最新版本詳細安裝教程(附安裝包)

目錄 文章自述 一、JAVA下載 二、JAVA安裝 1.首先在D盤創建【java/jdk-23】文件夾 2.把下載的壓縮包移動到【jdk-23】文件夾內&#xff0c;右鍵點擊【解壓到當前文件夾】 3.如圖解壓會有【jdk-23.0.1】文件 4.右鍵桌面此電腦&#xff0c;點擊【屬性】 5.下滑滾動條&…

基于javaweb的SpringBoot個人博客系統設計和實現(源碼+文檔+部署講解)

技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論…

三、linux字符驅動詳解

在上一節完成NFS開發環境的搭建后&#xff0c;本節將探討Linux字符設備驅動的開發。字符設備驅動作為Linux內核的重要組成部分&#xff0c;主要負責管理與字符設備&#xff08;如串口、鍵盤等&#xff09;的交互&#xff0c;并為用戶空間程序提供統一的讀寫操作接口。 驅動代碼…

Python爬蟲處理網頁中的動態內容

文章目錄 前言一、Python環境搭建1.Python安裝2.選擇Python開發環境 二、Python爬蟲處理網頁中的動態內容1. 使用 Selenium 庫2. 使用 Pyppeteer 庫3. 分析 API 請求 前言 在網頁中&#xff0c;動態內容通常是指那些通過 JavaScript 在頁面加載后動態生成或更新的內容&#xf…

重學SpringBoot3-Spring Retry實踐

更多SpringBoot3內容請關注我的專欄&#xff1a;《SpringBoot3》 期待您的點贊??收藏評論 重學SpringBoot3-Spring Retry實踐 1. 簡介2. 環境準備3. 使用方式 3.1 注解方式 基礎使用自定義重試策略失敗恢復機制重試和失敗恢復效果注意事項 3.2 編程式使用3.3 監聽重試過程 監…

vue3中解決組件間 css 層級問題最佳實踐(Teleport的使用)

定義&#xff1a; <Teleport> 是 Vue 3 中引入的一個內置組件&#xff0c;用于將組件的內容渲染到 DOM 中的指定位置&#xff0c;而不受組件層級結構的限制。這在處理模態框、通知、下拉菜單等需要脫離當前組件層級的情況下非常有用。 通俗來說&#xff0c;Teleport的功…

密度提升30%!Intel 18A工藝正式開放代工

快科技2月23日消息&#xff0c;Intel官方網站悄然更新了對于18A(1.8nm級)工藝節點的描述&#xff0c;稱已經做好了迎接客戶項目的準備&#xff0c;將在今年上半年開始流片&#xff0c;有需求的客戶可以隨時聯系。 Intel宣稱&#xff0c;這是在北美地區率先量產的2nm以下工藝節…

docker中常用的命令

一、服務命令 systemctl start docker.service 啟動docker服務 systemctl stop docker.service 關閉docker服務 systemctl enable docker.service 設置docker服務開機啟動 systemctl disable docker.service .禁止docker服務開機自啟動 二、鏡像命令 d…

架構師論文《智慧醫療系統中的數據集成與共享》

智慧醫療系統中的數據集成與共享 摘要 隨著醫療信息化的發展&#xff0c;如何實現跨系統、跨機構的數據集成與共享成為智慧醫療建設的核心問題。2019年&#xff0c;我所在的醫療科技公司承接了某省衛生健康委員會主導的“區域醫療信息化平臺”項目。該平臺旨在整合區域內三甲醫…

請求go構建緩存,go clean -cache

go clean -cache go 構建時會產生很多緩存&#xff0c; 一般是目錄&#xff1a;/Users/xxx/Library/Caches/go-build 此目錄README&#xff1a; This directory holds cached build artifacts from the Go build system. Run "go clean -cache" if the directory …

mybatis從接口直接跳到xml的插件

在使用 MyBatis(包括 MyBatis-Plus)時,如果你希望從接口方法直接跳轉到對應的 XML 映射文件中的 SQL 語句定義,可以借助一些開發工具或插件來實現這一功能。以下是幾種常見的方法和插件推薦: 方法一:使用 IDE 內置功能 IntelliJ IDEA IntelliJ IDEA 提供了對 MyBatis …

計算機視覺行業洞察--影像行業系列第一期

計算機視覺行業產業鏈的上下游構成相對清晰&#xff0c;從基礎技術研發到具體應用場景的多個環節相對成熟。 以下是我結合VisionChina經歷和行業龍頭企業對計算機視覺行業產業鏈上下游的拆解總結。 上下游總結 上游產業鏈分為軟硬件兩類&#xff0c;視覺的硬件主要指芯片、…

Spring事務原理 二

在上一篇博文《Spring事務原理 一》中&#xff0c;我們熟悉了Spring聲明式事務的AOP原理&#xff0c;以及事務執行的大體流程。 本文中&#xff0c;介紹了Spring事務的核心組件、傳播行為的源碼實現。下一篇中&#xff0c;我們將結合案例&#xff0c;來講解實戰中有關事務的易…

邏輯函數的神經網絡實現

1.單層感知器實現基本邏輯函數 先給大家拋出一道例題 &#xff08;一&#xff09;種類 a.OR函數 目標&#xff1a;當至少一個輸入為1時&#xff0c;輸出1&#xff1b;否則輸出0。 權重設置&#xff1a; 輸入權重&#xff1a;所有 wi1&#xff08;i1,2,...,m&#xff09;。…

SF-HCI-SAP問題收集1

最近在做HCI的集成&#xff0c;是S4的環境&#xff0c;發現很多東西都跑不通&#xff0c;今天開始收集一下錯誤點 如果下圖沖從0001變成0010&#xff0c;sfiom_rprq_osi表就會存數據&#xff0c;系統檢查到此表就會報錯&#xff0c;這個選項的作用就是自定義信息類型也能更新&a…

(面試經典問題之分布式鎖)分布式鎖的基本原理、作用以及實現

一、什么是分布式鎖 分布式鎖指的是在分布式場景中實現互斥類型的鎖。 分布式是什么意思&#xff1f;分布式表示運行的節點可能在不同的機器或不同的網段中&#xff0c;節點間通信通過socket。互斥類型是什么意思&#xff1f;互斥類型表示同一時刻只允許一個執行體進入臨界資…

機械硬盤與固態硬盤的區別-機械硬盤的未來在哪里?

隨著近年來固態硬盤的技術成熟和成本的下探&#xff0c;固態硬盤&#xff08;SSD&#xff09;儼然有要取代傳統機械硬盤&#xff08;HDD&#xff09;的趨勢&#xff0c;但目前單位容量下機械硬盤每GB價格相比閃存還有5-7倍的優勢&#xff0c;那么機械硬盤是否已經發展到極限&am…

06排序 + 查找(D1_排序(D1_基礎學習))

目錄 學習預熱&#xff1a;基礎知識 一、什么是排序 二、為什么要排序 三、排序的穩定性 四、排序穩定性的意義 五、排序分類方式 方式一&#xff1a;內外分類 方式二&#xff1a;比較分類 六、排序算法性能評估 1. 算法的時間復雜度 2. 算法的空間復雜度 七、知識小…

簡訊:Rust 2024 edition and v1.85.0 已發布

詳見 https://blog.rust-lang.org/2025/02/20/Rust-1.85.0.html 升級方法&#xff1a;rustup update stable