兩數之和(Hash表)

優質博文:IT-BLOG-CN

一、題目

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

你可以假設每種輸入只會對應一個答案。但是,數組中同一個元素在答案里不能重復出現。

你可以按任意順序返回答案。

示例 1:
輸入:nums = [2,7,11,15], target = 9
輸出:[0,1]
解釋:因為nums[0] + nums[1] == 9,返回[0, 1]

示例 2:
輸入:nums = [3,2,4], target = 6
輸出:[1,2]

示例 3:
輸入:nums = [3,3], target = 6
輸出:[0,1]

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只會存在一個有效答案

進階: 你可以想出一個時間復雜度小于O(n2)的算法嗎?

二、代碼

哈希表思路:
【1】先獲取數組中的第一個元素,通過target - num[i] = x,直接過去x的下標,存在直接返回當前索引和查詢到的索引,但需要對[3,3]=6等特殊場景進行處理。
【2】們發現這個題目屬于hash表下面的,所以使用hash表來實現。可以用key保存數值,用value在保存數值所在的下標map中的存儲結構為{key:數據元素,value:數組元素對應的下表}

在遍歷數組的時候,只需要向map去查詢是否存在target - num[i] = x中的x,如果存在,就返回value也就是下標和i,如果沒有,就把目前遍歷的元素放進map中,因為map存放的就是我們訪問過的元素。

class Solution {public int[] twoSum(int[] nums, int target) {// 先獲取數組中的第一個元素,通過 target - num[i] = x, 直接過去x的下標,存在直接返回,需要對[3,3]相同的做特殊處理。// 我們發現這個題目屬于 hash表下面的,所以使用hash表來實現。可以用key保存數值,用value在保存數值所在的下標// map中的存儲結構為 {key:數據元素,value:數組元素對應的下表}int[] res = new int[2];Map<Integer,Integer> map = new HashMap();for (int i = 0; i < nums.length; i++) {int x = target - nums[i];if (map.containsKey(x)) {res[0] = map.get(x);res[1] = i;return res;}map.put(nums[i], i);}return res;}
}

時間復雜度: O(N),其中N是數組中的元素數量。對于每一個元素x,我們可以O(1)地尋找target - x
空間復雜度: O(N),其中N是數組中的元素數量。主要為哈希表的開銷。

暴力枚舉: 最容易想到的方法是枚舉數組中的每一個數x,尋找數組中是否存在target - x

當我們使用遍歷整個數組的方式尋找target - x時,需要注意到每一個位于x之前的元素都已經和x匹配過,因此不需要再進行匹配。而每一個元素不能被使用兩次,所以我們只需要在x后面的元素中尋找target - x

class Solution {public int[] twoSum(int[] nums, int target) {int n = nums.length;for (int i = 0; i < n; ++i) {for (int j = i + 1; j < n; ++j) {if (nums[i] + nums[j] == target) {return new int[]{i, j};}}}return new int[0];}
}

時間復雜度: O(N^2),其中N是數組中的元素數量。最壞情況下數組中任意兩個數都要被匹配一次。
空間復雜度: O(1)

思考:
1、如果nums是有序的,是否還需要哈希表?換句話說,能否做到O(1)額外空間?
2、如果要求尋找三個數,它們的和等于target呢?

含有重復元素的兩數之和(字節算法工程師面試題) :給定一個可能包含重復元素的有序數組,以及一個目標值target。計算數組中有多少對兩個整數的組合滿足和等于target
示例1: nums=[2,2,2,2], target= 4, ans=6
示例2: nums=[1,1,2,2,2,2,3,3], target=4, ans=10
示例3: nums=[1,1,1,1], target=4, ans=0

其實第一眼看上去倒也不難,就是一個變體的兩數之和。所以剛開始的思路就是先統計每一個數出現的次數,然后再按照兩數之和的方法去算,只不過算的時候要考慮兩個數出現的次數相乘才是所有的組合。

但是面試官說還有更好的,讓我往三數之和上想。但是我想偏了,我一直想的是在三數之和中如果當前數和前一個數相等,那么會直接跳過。這里的話應該是可以根據前一個數對答案的貢獻度直接推出來當前數的貢獻度的。比如[1,1,2,2,2,2,4,4]的測試用例,首先第一次計算出第一個1對結果的貢獻度是2之后,指針右移,又遇到一個1,那么可以不用計算,直接加上上一次的答案,同理,第一次遇到2也是,但是由于2 = 4 - 2,所以,第二次遇到2的時候,不能直接加上上一次的答案,應該加上上一次的答案-1

import bisect
def solve(nums, target):ans = 0pre = 0for i, num in enumerate(nums):if num == target - num:r = bisect.bisect_right(nums, num)ans += (r - i) * (r - i - 1) // 2return ansif i > 0 and nums[i-1] == num:ans += precontinuel, r = bisect.bisect_left(nums, target - num), bisect.bisect_right(nums, target - num)if l < r:ans += r - lpre = r - lreturn ans

面試完又想了一下另一個思路,可以按照三數之和內層循環的思路,用兩個指針分別指向首尾,
1、如果這兩個數的和小于taregt,右移左指針,
2、如果大于target,左移右指針。
3、如果等于target,分情況討論
4、如果兩個數相等,可以直接計算,然后終止循環。因為數組有序,繼續循環下去也沒意義。
5、如果兩個數不相等,分別計算出左右兩個數出現的次數。然后再計算對答案的貢獻度。

時間復雜度: 因為每個數最多只會遍歷一次,所以是O(n)
空間復雜度: 只需要常數級的額外空間,所以是:O(1)

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:ans = 0left, right = 0, len(nums) - 1while left <= right:current_sum = nums[left] + nums[right]if current_sum == target:# 找到一組滿足條件的組合if nums[left] == nums[right]:ans += (right - left + 1) * (right - left) // 2break# 統計左右兩個數各自出現的次數left_num, right_num = 1, 1left += 1right -= 1while left <= right and nums[left] == nums[left - 1]:left_num += 1left += 1while left <= right and nums[right] == nums[right + 1]:right_num += 1right -= 1ans += left_num * right_numelif current_sum < target:left += 1else:right -= 1return ans

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

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

相關文章

C++8--賦值運算符重載

1.運算符重載 C引入運算符的目的是為了增強代碼的可讀性。運算符重載是具有特殊函數名的函數&#xff0c;也具有其返回值類型&#xff0c;函數名字以及參數列表&#xff0c;其返回值類型與參數列表與普通的函數相似。 函數名字為&#xff1a;關鍵字operator后面接需要重載的運算…

P1255 數樓梯

剛開始使用暴力進行求解&#xff0c;結果發現這是一道考驗高精度的題目&#xff0c;后來用高精度的方法&#xff0c;甚至使用到了容器&#xff0c;結果還不如暴力求解的60分&#xff0c;后來看了題解&#xff0c;有一個非常好的思路&#xff0c;即體現了高精度求和&#xff0c;…

pyfink1.20版本下實現消費kafka中數據并實時計算

1、環境 JDK版本&#xff1a;1.8.0_412python版本&#xff1a;3.10.6apache-flink版本&#xff1a;1.20.0flink版本&#xff1a;1.20kafka版本&#xff1a;kafka_2.12-3.1.1flink-sql-connector-kafka版本&#xff1a;3.3.0-1.202、執行python-flink腳本 從kafka的demo獲取消…

數據結構速成

1. 數據結構與算法 2. 順序表 3. 鏈表 4. 棧與隊列 5. 串 6. 樹與二叉樹&#xff08;1&#xff09; 7. 樹與二叉樹&#xff08;2&#xff09; 8. 圖 9. 圖的應用 10. 查找 11. 排序&#xff08;1&#xff09; 12. 排序&#xff08;2&#xff09;

k8s的污點與容忍度

污點&#xff08;Taint&#xff09;針對節點來說&#xff0c;和節點親和性正好相對&#xff0c;節點親和性使Pod被吸引到一類特定的節點&#xff0c;而污點則使節點能夠排斥一類特定的Pod。 容忍度&#xff08;Toleration&#xff09;應用于Pod上&#xff0c;它用來允許調度器…

how to write 述職pptx as a tech manager

As a technical manager, crafting an effective 述職 (performance review) PPT requires you to highlight your leadership, team accomplishments, technical contributions, challenges faced, and future plans. Heres a structured approach to design your PPT: 1. Cov…

從源碼層級深入探索 Spring AMQP 如何在 Spring Boot 中實現 RabbitMQ 集成——消費者如何進行消費

本章節主要從底層源碼探索Spring Boot中RabbitMQ如何進行消費&#xff0c;至于RabbitMQ是如何使用如何生產消息&#xff0c;本章不做過多介紹&#xff0c;感興趣的小伙伴可以參考&#xff1a;從源碼層級深入探索 Spring AMQP 如何在 Spring Boot 中實現 RabbitMQ 集成——生產者…

計算機視覺中的邊緣檢測算法

摘要&#xff1a; 本文全面深入地探討了計算機視覺中的邊緣檢測算法。首先闡述了邊緣檢測的重要性及其在計算機視覺領域的基礎地位&#xff0c;隨后詳細介紹了經典的邊緣檢測算法&#xff0c;包括基于梯度的 Sobel 算子算法、Canny 邊緣檢測算法等&#xff0c;深入剖析了它們的…

Unix 和 Windows 的有趣比較

Unix 和 Windows NT 比較 來源于這兩本書&#xff0c;把兩本書對照來讀&#xff0c;發現很多有意思的地方&#xff1a; 《Unix 傳奇》 https://book.douban.com/subject/35292726/ 《觀止 微軟創建NT和未來的奪命狂奔 》 Showstopper!: The Breakneck Race to Create Windows…

SSM 垃圾分類系統——高效分類的科技保障

第五章 系統功能實現 5.1管理員登錄 管理員登錄&#xff0c;通過填寫用戶名、密碼、角色等信息&#xff0c;輸入完成后選擇登錄即可進入垃圾分類系統&#xff0c;如圖5-1所示。 圖5-1管理員登錄界面圖 5.2管理員功能實現 5.2.1 用戶管理 管理員對用戶管理進行填寫賬號、姓名、…

系列1:基于Centos-8.6部署Kubernetes (1.24-1.30)

每日禪語 “木末芙蓉花&#xff0c;山中發紅萼&#xff0c;澗戶寂無人&#xff0c;紛紛開自落。?”這是王維的一首詩&#xff0c;名叫《辛夷塢》?。這首詩寫的是在辛夷塢這個幽深的山谷里&#xff0c;辛夷花自開自落&#xff0c;平淡得很&#xff0c;既沒有生的喜悅&#xff…

Y20030004基于asp.net+Sql的環保網站的設計與實現(附源碼 調試 文檔)

環保網站的設計與實現 1.摘要要2. 系統功能3.功能結構圖4.界面展示5.源碼獲取 1.摘要要 近幾年國家對于環境管理是高度重視&#xff0c;尤其是對于環境生態的破壞與環境污染&#xff0c;已經嚴重影響到人類的生存和發展。為了使生態環境能夠得到保護和改善&#xff0c;持續發展…

安全計算環境-(一)路由器-1

安全計算環境-網絡設備 安全管理中心針對整個系統提出了安全管理方面的技術控制要求&#xff0c;通過技術手段實現集中管理&#xff1b;涉及的安全控制點包括系統管理、審計管理、安全管理和集中管控。以下以三級等級保護對象為例&#xff0c;描述安全管理中心各個控制要求項的…

D9741是一塊脈寬調制方三用于也收路像機和筆記本電的等設備上的直流轉換器。在便攜式的儀器設備上。

概述&#xff1a; D9741是一塊脈寬調制方三用于也收路像機和筆記本電的等設備上的直流轉換器。在便攜式的儀器設備上。 主要特點&#xff1a; ● 高精度基準電路 ● 定時閂鎖、短路保護電路 ● 低電壓輸入時誤操作保護電路 ● 輸出基準電壓(2.5V) ● 超過工作范圍能進行自動校…

數據挖掘之聚類分析

聚類分析&#xff08;Clustering Analysis&#xff09; 是數據挖掘中的一項重要技術&#xff0c;旨在根據對象間的相似性或差異性&#xff0c;將對象分為若干組&#xff08;簇&#xff09;。同一簇內的對象相似性較高&#xff0c;而不同簇間的對象差異性較大。聚類分析廣泛應用…

Qt 圖形框架下圖形拖動后位置跳動問題

在使用Qt 的圖形框架QGraphicsScene&#xff0c;QGraphicsView實現圖形顯示時。遇到一個很棘手的BUG。 使用的圖形是自定義的QGraphicsObject的子類。 現象是將圖形添加到畫布上之后&#xff0c;用鼠標拖動圖形&#xff0c;圖形能正常改變位置&#xff0c;當再次用鼠標點擊圖…

Vue技術中參數傳遞:Props與事件的實踐指南

在Vue.js中&#xff0c;組件間的參數傳遞是構建動態和交互式應用的核心。本文將深入探討如何通過Props和事件&#xff08;$emit&#xff09;在Vue組件間進行參數傳遞&#xff0c;并提供代碼示例。 Props傳遞數據 Props是Vue中組件間傳遞數據的一種方式&#xff0c;它允許父組…

一、LRU緩存

LRU緩存 1.LRU緩存介紹2.LRU緩存實現3.LRU緩存總結3.1 LRU 緩存的應用3.2 LRU 緩存的優缺點 1.LRU緩存介紹 LRU是Least Recently Used 的縮寫&#xff0c;意為“最近最少使用”。它是一種常見的緩存淘汰策略&#xff0c;用于在緩存容量有限時&#xff0c;決定哪些數據需要被刪…

LabVIEW光柵衍射虛擬仿真系統

隨著現代教育技術的快速發展&#xff0c;虛擬仿真實驗平臺逐漸成為物理實驗教學的重要輔助工具。基于LabVIEW的平面透射光柵虛擬仿真系統幫助學生更好地理解和分析光柵衍射現象&#xff0c;提高教學質量和學生的學習興趣。 項目背景 在波動光學的教學中&#xff0c;光柵衍射實…

241211 selenium問題記錄

The process started from chrome location /usr/bin/chromedriver is no longer running, so ChromeDriver is assuming that Chrome has crashed. 聲明option類 chrome_option.add_argument(--headless) 后臺啟動webdriver NoSuchDriverException(msg) from err selenium.c…