演算法 兩數之和,三數之和,四數之和

2021-10-02 07:36:58 字數 4277 閱讀 4128

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

你可以假設每種輸入只會對應乙個答案。但是,你不能重複利用這個陣列中同樣的元素。

示例:

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

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

所以返回 [0, 1]

暴力法很簡單,遍歷每個元素 xx,並查詢是否存在乙個值與 target - xtarget−x 相等的目標元素。

class

solution;}

}}throw

newillegalargumentexception

("no two sum solution");

}}

複雜度分析:

為了對執行時間複雜度進行優化,我們需要一種更有效的方法來檢查陣列中是否存在目標元素。如果存在,我們需要找出它的索引。保持陣列中的每個元素與其索引相互對應的最好方法是什麼?雜湊表。

通過以空間換取速度的方式,我們可以將查詢時間從 o(n)降低到 o(1)。雜湊表正是為此目的而構建的,它支援以近似恆定的時間進行快速查詢。我用「近似」來描述,是因為一旦出現衝突,查詢用時可能會退化到 o(n)。但只要你仔細地挑選雜湊函式,在雜湊表中進行查詢的用時應當被攤銷為 o(1)。

乙個簡單的實現使用了兩次迭代。在第一次迭代中,我們將每個元素的值和它的索引新增到表中。然後,在第二次迭代中,我們將檢查每個元素所對應的目標元素(target - nums[i])是否存在於表中。注意,該目標元素不能是 nums[i] 本身!

class solution 

for (int i = 0; i < nums.length; i++) ;}}

throw new illegalargumentexception("no two sum solution");

}}

複雜度分析:

我們可以一次完成。在進行迭代並將元素插入到表中的同時,我們還會回過頭來檢查表中是否已經存在當前元素所對應的目標元素。如果它存在,那我們已經找到了對應解,並立即將其返回。

class solution ;

}map.put(nums[i], i);

}throw new illegalargumentexception("no two sum solution");

}}

複雜度分析:

給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。

注意:答案中不可以包含重複的三元組。

示例:

給定陣列 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合為:

[[-1, 0, 1],

[-1, -1, 2]

]

三個for迴圈找到所有符合條件的元素組合, 然後對結果集進行去重。

複雜度分析:

演算法流程:

特判,對於陣列長度 n,如果陣列為 null 或者陣列長度小於 3,返回 。

對陣列進行排序。

首先對陣列進行排序

排序後固定乙個數 nums[i],再使用左右指標指向nums[i]後面的兩端,數字分別為 nums[l] 和 nums[r],計算三個數的和 sum 判斷是否滿足為 0,滿足則新增進結果集

如果 nums[i]大於 0,則三數之和必然無法等於0,結束迴圈

如果 nums[i] == nums[i−1],則說明該數字重複,會導致結果重複,所以應該跳過

當 sum == 0 時,nums[l] == nums[l+1] 則會導致結果重複,應該跳過,l++

當 sum == 0 時,nums[r] == nums[r−1] 則會導致結果重複,應該跳過,r–r−−

class

solution

else

if(sum <

0) l++

;else

if(sum >

0) r--;}

}return ans;

}}

複雜度分析

給定乙個包含 n 個整數的陣列 nums 和乙個目標值 target,判斷 nums 中是否存在四個元素 a,b,c 和 d ,使得 a + b + c + d 的值與 target 相等?找出所有滿足條件且不重複的四元組。

注意:答案中不可以包含重複的四元組。

示例:

給定陣列 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

滿足要求的四元組集合為:

[[-1, 0, 0, 1],

[-2, -1, 1, 2],

[-2, 0, 0, 2]

]

基本思想就和 3sum 相同

先後固定其中兩個數值 i、j,再使用雙指標尋找與目標合適的差值

演算法流程

特判,對於陣列長度 n,如果陣列為 null 或者陣列長度小於 4,返回 。

對陣列進行排序。

首先對陣列進行排序

排序後固定乙個數 nums[i]

如果 nums[i]大於 0,則三數之和必然無法等於0,結束迴圈

如果 nums[i] == nums[i−1],則說明該數字重複,會導致結果重複,所以應該跳過

在固定乙個數 nums[j]

再使用左右指標指向nums[j]後面的兩端,數字分別為 nums[l] 和 nums[r],計算四個數的和 sum 判斷是否滿足為 0,滿足則新增進結果集

如果 nums[j] == nums[j−1],則說明該數字重複,會導致結果重複,所以應該跳過

當 sum == 0 時,nums[l] == nums[l+1] 則會導致結果重複,應該跳過,l++

當 sum == 0 時,nums[r] == nums[r−1] 則會導致結果重複,應該跳過,r–r−−

class

solution

/*對陣列進行從小到大排序*/

arrays.

sort

(nums)

;/*陣列長度*/

int length=nums.length;

/*定義4個指標k,i,j,h k從0開始遍歷,i從k+1開始遍歷,留下j和h,j指向i+1,h指向陣列最大值*/

for(

int k=

0;k3;k++

)/*獲取當前最小值,如果最小值比目標值大,說明後面越來越大的值根本沒戲*/

int min1=nums[k]

+nums[k+1]

+nums[k+2]

+nums[k+3]

;if(min1>target)

/*獲取當前最大值,如果最大值比目標值小,說明後面越來越小的值根本沒戲,忽略*/

int max1=nums[k]

+nums[length-1]

+nums[length-2]

+nums[length-3]

;if(max1/*第二層迴圈i,初始值指向k+1*/

for(

int i=k+

1;i2;i++

)/*定義指標j指向i+1*/

int j=i+1;

/*定義指標h指向陣列末尾*/

int h=length-1;

/*獲取當前最小值,如果最小值比目標值大,說明後面越來越大的值根本沒戲,忽略*/

int min=nums[k]

+nums[i]

+nums[j]

+nums[j+1]

;if(min>target)

/*獲取當前最大值,如果最大值比目標值小,說明後面越來越小的值根本沒戲,忽略*/

int max=nums[k]

+nums[i]

+nums[h]

+nums[h-1]

;if(max/*開始j指標和h指標的表演,計算當前和,如果等於目標值,j++並去重,h--並去重,當當前和大於目標值時h--,當當前和小於目標值時j++*/

while

(jh--

;while

(j==nums[h+1]

)}else

if(curr>target)

else}}

}return result;

}}

複雜度分析

兩數之和 三數之和 四數之和

兩數之和意思就是 給你乙個陣列,從中找出兩個數字,讓他們的和等於乙個具體的target。找到所有這樣的兩個數。並且這兩個數字不能完全一樣。n數之和的意思是 給你乙個陣列,從中找出n個數字,讓他們的和等於乙個具體的target。找到所有這樣的n個數。並且這n個數字不能完全一樣。最基礎的,也是最關鍵的就...

Leetcode 兩數之和,三數之和,四數之和

兩數之和的思想比較簡單啦 就是 使用乙個map儲存其值,然後將其下標返回即可 三數之和 四數之和的思想比較類似,就是使用雙指標的思想 三數之和的 如下所示 四數之和的 如下 有一些優化 四數之和是在三數之和的基礎上增加了一層迴圈,class solution 獲取當前最大值 int max1 num...

兩數之和 三數之和 四數之和cpp

給定乙個整數陣列 nums 和乙個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。你可以假設每種輸入只會對應乙個答案。但是,陣列中同乙個元素不能使用兩遍。class solution mp target nums i i return 給你乙個包含 n 個整...