1. 程式人生 > >求和問題總結(leetcode 2Sum, 3Sum, 4Sum, K Sum)

求和問題總結(leetcode 2Sum, 3Sum, 4Sum, K Sum)

前言:

做過leetcode的人都知道, 裡面有2sum, 3sum(closest), 4sum等問題, 這些也是面試裡面經典的問題, 考察是否能夠合理利用排序這個性質, 一步一步得到高效的演算法. 經過總結, 本人覺得這些問題都可以使用一個通用的K sum求和問題加以概括消化, 這裡我們先直接給出K Sum的問題描述和演算法(遞迴解法), 然後將這個一般性的方法套用到具體的K, 比如leetcode中的2Sum, 3Sum, 4Sum問題. 同時我們也給出另一種雜湊演算法的討論.

leetcode求和問題描述(K sum problem):

K sum的求和問題一般是這樣子描述的:給你一組N個數字(比如 vector<int> num), 然後給你一個常數(比如 int target) ,我們的goal是在這一堆數裡面找到K個數字,使得這K個數字的和等於target。

注意事項(constraints):

注意這一組數字可能有重複項:比如 1 1 2 3 , 求3sum, 然後 target  = 6, 你搜的時候可能會得到 兩組1 2 3, 1 2 3,1 來自第一個1或者第二個1, 但是結果其實只有一組,所以最後結果要去重。

K Sum求解方法, 適用leetcode 2Sum, 3Sum, 4Sum:

方法一: 暴力,就是列舉所有的K-subset, 那麼這樣的複雜度就是 從N選出K個,複雜度是O(N^K)

方法二: 排序,這個演算法可以考慮最簡單的case, 2sum,這是個經典問題,方法就是先排序,然後利用頭尾指標找到兩個數使得他們的和等於target, 這個2sum演算法網上一搜就有,這裡不贅述了,給出2sum的核心程式碼:

//2 sum
int i = starting; //頭指標
int j = num.size() - 1; //尾指標
while(i < j) {
    int sum = num[i] + num[j];
    if(sum == target) {
        store num[i] and num[j] somewhere;
        if(we need only one such pair of numbers)
            break;
        otherwise
            do ++i, --j;
    }
    else if(sum < target)
        ++i;
    else
        --j;
}

2sum的演算法複雜度是O(N log N) 因為排序用了N log N以及頭尾指標的搜尋是線性的,所以總體是O(N log N),好了現在考慮3sum, 有了2sum其實3sum就不難了,這樣想:先取出一個數,那麼我只要在剩下的數字裡面找到兩個數字使得他們的和等於(target – 那個取出的數)就可以了吧。所以3sum就退化成了2sum, 取出一個數字,這樣的數字有N個,所以3sum的演算法複雜度就是O(N^2 ), 注意這裡複雜度是N平方,因為你排序只需要排一次,後面的工作都是取出一個數字,然後找剩下的兩個數字,找兩個數字是2sum用頭尾指標線性掃,這裡很容易錯誤的將複雜度算成O(N^2 log N),這個是不對的。我們繼續的話4sum也就可以退化成3sum問題,那麼以此類推,K-sum一步一步退化,最後也就是解決一個2sum的問題,K sum的複雜度是O(n^(K-1))。 這個界好像是最好的界了,也就是K-sum問題最好也就能做到O(n^(K-1))複雜度,之前有看到過有人說可以嚴格數學證明,這裡就不深入研究了。

K Sum (2Sum, 3Sum, 4Sum) 演算法優化(Optimization):

這裡講兩點,第一,注意比如3sum的時候,先整體排一次序,然後列舉第三個數字的時候不需要重複, 比如排好序以後的數字是 a b c d e f, 那麼第一次列舉a, 在剩下的b c d e f中進行2 sum, 完了以後第二次列舉b, 只需要在 c d e f中進行2sum好了,而不是在a c d e f中進行2sum, 這個大家可以自己體會一下,想通了還是挺有幫助的。第二,K Sum可以寫一個遞迴程式很優雅的解決,具體大家可以自己試一試。寫遞迴的時候注意不要重複排序就行了。

Hash解法(Other):

其實比如2sum還是有線性解法的,就是用hashmap, 這樣你check某個值存在不存在就是常數時間,那麼給定一個sum, 只要線性掃描, 對每一個number判斷sum – num存在不存在就可以了。注意這個演算法對有重複元素的序列也是適用的。比如 2 3 3 4 那麼hashtable可以使 hash(2) = 1; hash(3) = 1, hash(4) =1其他都是0,  那麼check的時候,掃到兩次3都是check sum – 3在不在hashtable中,注意最後返回所有符合的pair的時候也還是要去重。這樣子推廣的話 3sum 其實也有O(N^2)的類似hash演算法,這點和之前是沒有提高的,但是4sum就會有更快的一個演算法。

4sum的hash演算法:

O(N^2)把所有pair存入hash表,並且每個hash值下面可以跟一個list做成map, map[hashvalue] = list,每個list中的元素就是一個pair, 這個pair的和就是這個hash值,那麼接下來求4sum就變成了在所有的pair value中求 2sum,這個就成了線性演算法了,注意這裡的線性又是針對pair數量(N^2)的線性,所以整體上這個演算法是O(N^2),而且因為我們掛了list, 所以只要符合4sum的我們都可以找到對應的是哪四個數字。
關於hash的解法我研究還不是很多,以後要是有更深入的研究再更新。

結束語:

這篇文章主要想從一般的K sum問題的角度總結那些比較經典的求和問題比如leetcode裡面的2sum, 3sum(closest), 4sum等問題,  文章先直接給出K Sum的問題描述和演算法(遞迴解法), 然後將這個一般性的方法套用到具體的K, 比如leetcode中的2Sum, 3Sum, 4Sum問題. 同時我們也給出另一種雜湊演算法的討論. 那麼這篇文章基本上還是自己想到什麼寫什麼,有疏忽不對的地方請大家指正,也歡迎留言討論,如果需要原始碼,請留言或者發郵件到[email protected]


相關推薦

求和問題總結(leetcode 2Sum, 3Sum, 4Sum, K Sum)

前言: 做過leetcode的人都知道, 裡面有2sum, 3sum(closest), 4sum等問題, 這些也是面試裡面經典的問題, 考察是否能夠合理利用排序這個性質, 一步一步得到高效的演算法. 經過總結, 本人覺得這些問題都可以使用一個通用的K sum求和

[leetcode]2sum,3sum,4sum總結

刷了50題了,本來是想50題一起總結的,發現並沒有啥耐心。還是邊刷邊總結吧。 2sums class Solution { public int[] twoSum(int[] nums, int target) { Map<Int

【演算法】2SUM/3SUM/4SUM問題

之前就總結過一些Leetcode上各種sum問題,今天再拿出來完整得總結一番。 nSUM問題是指,在一個數組中,找出n個數相加和等於給定的數,這個叫做nSUM問題。 常見的有2SUM,3SUM,4SUM問題,還有各種SUM問題的變種.

[LeetCode] 698. Partition to K Equal Sum Subsets

Problem Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are

LeetCode #862 Shortest Subarray with Sum at Least K

文章目錄 題目 Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there is no non-empty subar

leetcode 698. Partition to K Equal Sum Subsets(記憶化搜尋/狀壓dp)

int n,kk,aver,f[20]; class Solution { public: bool flag = false; void dfs(int cnt,vector<

leetcode -- 15. 3Sum 【問題轉化2sum + 避免重複計算的方法(規定次序)】

題目 Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array whic

leetCodeK Sum()問題

import java.util.*; //Given nums = [2, 7, 11, 15], target = 9, //Because nums[0] + nums[1] = 2 + 7 = 9, //return [0, 1]. //思路:先建立一個int[2]陣

leetcode #1 #15 #16 #18 #167 K-Sum Problem Solution

Problem Description Given an array S of n integers, are there any k elements in S such that a[1]+a

LeetCode 698 Partition to K Equal Sum Subsets

this pro 增加 pos code 有一種 hashset += problem Problem Description: Given an array of integers nums and a positive integer k, find whether

LeetCode 560. 和為K的子數組(Subarray Sum Equals K

子數組和 tor 之前 -s 一個 leetcode 更新 spa int 題目描述 給定一個整數數組和一個整數 k,你需要找到該數組中和為 k 的連續的子數組的個數。 示例 1 : 輸入:nums = [1,1,1], k = 2 輸出: 2 , [1,1]

leetcode 209. Minimum Size Subarray Sum

urn https scrip subarray () ins -s mar color https://leetcode.com/problems/minimum-size-subarray-sum/#/description 題目很簡單。題意就是求字符串中長度最小的一

LeetCode】064. Minimum Path Sum

ive rom right ott path sum 處理 tom ber its 題目: Given a m x n grid filled with non-negative numbers, find a path from top left to bottom ri

[leetcode-508-Most Frequent Subtree Sum]

參考 auto back pic map ack col push_back clu Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree su

leetcode:Reverse Nodes in k-Group

pre ont con i++ ava variable ret sta pos Reverse Nodes in k-Group Given a linked list, reverse the nodes of a linked list k a

[Leetcode] DP--300. 629. K Inverse Pairs Array

inpu fine all row column example pair tput output Given two integers n and k, find how many different arrays consist of numbers from 1 to

LeetCode 339. Nested List Weight Sum (嵌套列表重和)

cnblogs one time lists lds all logs sts not Given a nested list of integers, return the sum of all integers in the list weighted by thei

LeetCode 15. 3Sum(三數之和)

while arr cnblogs 關鍵點 next 資料 () code find Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find

k Sum II

lint list clas i++ move rem int oid arch Given n unique integers, number k (1<=k<=n) and target. Find all possible k integers whe

LeetCode[Array]----3Sum

integer 遍歷 [] http col word-wrap 兩個指針 article target 3Sum Given an array S of n integers, are there elements a, b, c in S such