Python陣列中求和問題
本專題主要介紹雜湊表和指標兩種方法來解決該類問題,從兩個數之和引申到三個數之和,再從四個數之和的問題上思考如何構建出一種通用的程式碼(可以解決N個數之和)。本文主要內容是通過001問題來初步瞭解陣列求和的兩種常用方法。
001-Two Sum
給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。
示例 :
給定 nums = [2, 7, 11, 15], target = 9
因為 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
- 暴力迴圈
O(n^2)
唯一需要注意的是同一個元素不能複用
nums_len = len(nums)
for
i
in
range(
0
, nums_len):
for
j
in
range(i +
1
, nums_len):
if
nums[i] + nums[j] == target:
return
[i, j]
- 雜湊
(1) O(n)
(2) 考慮暴力迴圈中我們做的事情,我們先挑出一個值a,然後看陣列中其他值是否能與值a相加等於目標,也可以說成看陣列中是否存在一個值等於目標值減去值a。
(3) 換個思路,我們將所有遍歷過的值存放起來,每次遍歷到一個新的值b時,我們可以查詢目標值減去值b是否在我們存放的值中。基於雜湊表的特性,查詢的時間複雜度為O(1),總時間複雜度就變為了一次for迴圈O(n)
回到本道題中:
(1) 由於需要返回對應的索引,所以需要使用HashMap(在python中是dict),key存放陣列中的值,value存放陣列中的索引,遍歷陣列,將遍歷過的值存入dict,如果目標值減去當前值在dict中則證明找到了目標值。
(2) 還有一點需要注意的是如果想按從小到大的順序返回值,dict中存放的肯定是前一個值(因為是之前遍歷過的)。
seen_dict = {}
for
i, num
in
enumerate(nums):
search = target - num
if
search
in
seen_dict:
return
[seen_dict[search], i]
else
:
seen_dict[num] = i
- 雙指標
(1) O(nlogn)-主要是快排的影響
(2) 在一個有序的陣列中最左邊一定是最小值,而最右邊一定是最大值。我們可以將最小值與最大值相加與目標值進行比較,如果兩數之和大於目標值,我們就讓最大值小一點(也就是讀取第二個最大值),相反如果小於,則讓最小值大一點(讀取第二個最小值)。這樣我們就保證了一次迴圈就能查詢到目標值,但陣列必須是有序的。
回到題目中:
(1) 由於需要返回索引,所以我們必須儲存兩個陣列,一個是無序的(用於查詢真實的索引),另一個是有序的(用於查詢符合題目的值)。
(2) 兩個指標left和right分別指向陣列中第一個元素和最後一個元素(最小值和最大值)
(3) 迴圈的結束條件為左指標大於等於右指標(左邊的不能比右邊的大,而且一個元素只能用一次)
(4) 然後就判斷左值+右值與目標值之間的關係,在上面我們已經討論過了大於和小於的情況。
(5) 當等於時由於我們需要得到左值和右值在原本陣列的索引,我們需要考慮以下問題。從題目中的得知每個target只有一個答案, 意味著如果target是6不會出現[2, 2, 4]的情況, 但是會出現[3, 3]的情況, 也就是當兩個相同的值滿足情況是才會有重複的元素。所以我們先通過index獲取左值對應的索引,如果左值和右值相同我們就獲取下一個該值的索引,如果不同,我們直接獲取右值相關的索引。
raw_nums = nums
nums = sorted(nums)
left, right =
0
, len(nums) -
1
while
left < right:
v_left, v_right = nums[left], nums[right]
two_sum = v_left + v_right
if
two_sum > target:
right -=
1
elif
two_sum < target:
left +=
1
else
:
# 找到了
left_index = raw_nums.index(v_left)
# 如果值相同就查詢下一個該值的索引
right_index = raw_nums.index(v_right, left +
1
)
if
v_right == v_left
else
raw_nums.index(v_right)
return
[left_index, right_index]
總結
通過兩個數求和問題初步瞭解陣列求和問題,下一文將引申這兩種方法在三個數求和中的應用。
原文釋出時間為:2018-08-04
本文作者:dyq666
本文來自雲棲社群合作伙伴“ Python中文社群”,瞭解相關資訊可以關注“ Python中文社群”
相關文章
- Python如何對二維陣列求和Python陣列
- JavaScript建立陣列求和JavaScript陣列
- 用Python解決一個等差數列的求和問題Python
- 陣列去重和求和陣列
- 陣列求和,刪除,去重陣列
- JS中的陣列複製問題JS陣列
- php陣列問題PHP陣列
- leetcode題解(陣列問題)LeetCode陣列
- 不可變陣列的範圍求和陣列
- vue中陣列變動不被監測問題Vue陣列
- 一維陣列:相鄰兩數求和陣列
- latex 中求和符號、箭頭問題符號
- js陣列全排列問題JS陣列
- TopK問題,陣列中第K大(小)個元素問題總結TopK陣列
- 簡單介紹最新python 字串陣列互轉問題Python字串陣列
- vue 陣列和物件渲染問題Vue陣列物件
- 陣列累加和問題三連陣列
- 子陣列異或和問題陣列
- 陣列效能問題分析總結陣列
- python中怎麼列印陣列Python陣列
- python中怎麼求和Python
- 陣列(引用型別)複製問題陣列型別
- 陣列和列表的轉換問題陣列
- C++陣列預設初值問題C++陣列
- 最大子陣列問題(Maximum subarray problem)陣列
- js 中基礎資料結構陣列去重問題JS資料結構陣列
- LeetCode 26 號問題 刪除陣列中的重複項LeetCode陣列
- 隔列求和
- 在迴圈陣列時使用splice()方法刪除陣列遇到的問題陣列
- 雙指標查詢陣列的連續規律子陣列問題指標陣列
- 尋找兩個正序陣列的中位數問題,方法一:合併陣列檢索法陣列
- 陣列的最小不可組成和問題陣列
- 子陣列的最大異或和問題陣列
- LeetCode題解(1550):陣列中存在連續三個奇數(Python)LeetCode陣列Python
- 陣列題目陣列
- 陣列 題目陣列
- 數學建模例題2.30 矩陣元素求和示例矩陣
- C----陣列越界問題、指標入門陣列指標