原題如下:
將寫有數(shù)字的n個紙片放入一個紙箱子中,然后你和你的朋友從紙箱子中抽取4張紙片,每次記下紙片上的數(shù)字后放回子箱子中,如果這4個數(shù)字的和是m,代表你贏,否則就是你的朋友贏。
請編寫一個程序,當(dāng)紙片上所寫的數(shù)字是a1,a2,a3,a4,..,an時,是否存在抽取4次和為m的方案,如果存在,輸出YES;否則,輸出NO。
首先想到最簡單的方案是直接4層循環(huán):
func jude(_ m: Int, _ a: [Int]) -> Bool {
for a1 in a {
for a2 in a {
for a3 in a {
for a4 in a {
if a1 + a2 + a3 + a4 == m {
return true
}
}
}
}
}
return false
}
時間復(fù)雜度是O(n^4),這個時間復(fù)雜度太大了。。。
給定的條件是:
ai + aj + as + at = m
我們可以變換一下等式,使之成為:
(ai + aj) + (as + at) = m
這樣就變成了找兩個數(shù)的和等于定值了:
a + b = sum
a、b可以看成是數(shù)組中任意兩個數(shù)組相加的合值。那么求解過程可以表示為先算出數(shù)組中任意兩個數(shù)兩兩相加的一個新數(shù)組,然后在這個新數(shù)組中找兩個數(shù),使得他們的和等于定值。
var sumArray = [Int]()
for a1 in a {
for a2 in a {
let sum = a1 + a2
sumArray.append(sum)
}
}
得到數(shù)組中任意兩數(shù)兩兩相加和的數(shù)組sumArray.
尋找兩個數(shù)的和為定值:
for s1 in sumArray {
for s2 in sumArray {
if m == s1 + s2 {
return true
}
}
}
完整代碼如下:
func jude(_ m: Int, _ a: [Int]) -> Bool {
var sumArray = [Int]()
for a1 in a {
for a2 in a {
let sum = a1 + a2
sumArray.append(sum)
}
}
for s1 in sumArray {
for s2 in sumArray {
if m == s1 + s2 {
return true
}
}
}
return false
}
測試一下:
let ret = jude(10, [1, 3, 5])
print(ret)//true
let ret = jude(9, [1, 3, 5])
print(ret)//false
這種解法的時間復(fù)雜度是O(n^2)。