題解:三數之和的多種可能(923)
阿新 • • 發佈:2018-12-21
給定一個整數陣列 A
,以及一個整數 target
作為目標值,返回滿足 i < j < k
且 A[i] + A[j] + A[k] == target
的元組 i, j, k
的數量。
由於結果會非常大,請返回 結果除以 10^9 + 7 的餘數
。
示例 1:
輸入:A = [1,1,2,2,3,3,4,4,5,5], target = 8 輸出:20 解釋: 按值列舉(A[i],A[j],A[k]): (1, 2, 5) 出現 8 次; (1, 3, 4) 出現 8 次; (2, 2, 4) 出現 2 次; (2, 3, 3) 出現 2 次。
示例 2:
輸入:A = [1,1,2,2,2,2], target = 5 輸出:12 解釋: A[i] = 1,A[j] = A[k] = 2 出現 12 次: 我們從 [1,1] 中選擇一個 1,有 2 種情況, 從 [2,2,2,2] 中選出兩個 2,有 6 種情況。
提示:
3 <= A.length <= 3000
0 <= A[i] <= 100
0 <= target <= 300
這道題剛開始我用的是遍歷,但是會超時,加進去了條件判斷跳出等優化也不行,只好再想辦法
然後我又想到了用雜湊來儲存,畢竟A[i]<=100,用了雜湊之後分析了一下條件
把所有可能都列一下 題目要求x<y<z 但是對應值 i<=j<=k 3 * i != target i + j + k = target //三數之和等於target i = j != k B(i) >= 2 // i=j 有兩個以上的j ((B(i) * (B(i)-1)) / 2) * B(k) B(i) < 2 // i=j 但是隻有一個i 0 i != j == k B(j) >= 2 // j=k 有兩個以上的j ((B(j) * (B(j)-1)) / 2) * B(i) B(j) < 2 // j=k 但是隻有一個j 0 i != j != k //三個數不同 B(i) * B(j) * B(k) i + j + k != target // 不等於target 0 3 * i == target //三個相同數的和等於target B(i) >= 3 //有三個以上相同的數 B(i) * (B(i)-1) * (B(i) -2) / (3 * 2 * 1) B(i) < 3 //相同數小於三個 0
列條件的時候覺得條件很多,如果一條條列出來的話會很麻煩,但是列出來之後發現有許多可以合併的條件,比如i==j!=k的兩種情況就可以合併,因為當B(i)<2時,B(i)=1,B(i)-1=0,表示式的值為0,所以將可以合併的判斷合併之後就會只剩下四個,但是再一分析發現,i=j!=k和i!=j=k其實是一個條件,只不過i,j,k的取值不同,但是隻用一個判斷條件的話後面也能判斷到另一個條件,所以最終合併之後會只有三個條件。分別是i=j=k,i=j!=k,i!=j!=k,然後寫出程式碼
object Solution { def threeSumMulti(A: Array[Int], target: Int): Int = { var result:Double = 0 //防止數字過大超範圍 val B = new Array[Int](105) //防止越界 for(i <- 0 until(A.length)) B(A(i)) += 1 //雜湊 for(i <- 0 until B.length){ for(j <- 0 until B.length){ if(B(i)!=0&&B(j)!=0){ //存在i和j val k = target - i - j if(k>=0&&k<=100 && B(k)>0){ //k存在 if(i == j && j == k) //i==j==k result += (B(i).toDouble * (B(i) - 1) * (B(i) - 2)) / 6 else if(i == j && j != k) //i==j!=k result += (B(i) * (B(i) - 1)) / 2 * B(k) else if(i < j && j < k) //i!=j!=k result += B(i) * B(j) * B(k) } } } } (result % 1000000007).toInt } }