小問題:求隨機給定100個數中相加和爲0的3個數

女票去面試,遇到個面試官提了個算法題,問題大概是“求隨機給定100個數中相加和爲0的3個數”,其實算法題在面試的過程中出到都是很常見的,不過這在短時間內可能很難想到。回來女票問我這個問題,她很好奇我爲什麼這麼快能打上來?emmm,說腦子好使會不會被打,哈哈哈,今天來講下這類題的一種套路。

1.遇到數,先排序,沒錯的

在遇到問題沒有立馬出現思路我覺得這是非常正常的事情,但是可以很明確的說,在對於數做操作的時候,有序會比無序好操作的多,畢竟有序的時候我可以採取的方式也就會更多。

2.3個數不好想,那轉換成2個呢?

這其實描述性的來說,就是把複雜問題簡單化。就拿這個問題來說吧,我在100個數裏面取三個數的和爲0可能很難處理,最笨的方法就是三層循環,o(n^3),在實在想不出來的時候,就說這個吧。

但是轉念想想,如果我們把這個問題轉化爲,求兩個數的和等於另一個數的相反數呢?這是不是就有了點眉目了呢?

3.問題變爲了,有序的100個數中,求兩數和 爲 x的項,是不是開始才思泉涌

具體講下大概的算法,將100個數排序後存到數組 a 中,開始循環數組a,索引爲i,然後分別取兩頭索引left,right對應的值a[left], a[right]的和是否等於該a[i],在不相等時,在根據 a[left] + a[right] 和與 a[i] 的大小關係,來判斷是將left+1 還是講 right + 1 再進行比對。

4.寫出大體代碼

如果覺得語言描述不清,寫出能代表你基本思路的代碼即可,也不需要能夠嚴格執行,最擅長php,就以php爲例

$left = 0;
$right = count($a) - 1;
foreach($a as $i => $sum) {
    $_left = $left;
    $_right = $right;
    while($_left < $_right) {
        if($a[$_left] + $a[$_right] < -$a[$i]) {
            $_left ++;
            if($_left == $i) $_left ++;
        } elseif ($a[$_left] + $a[$_right] > -$a[$i]) {
            $_right --;
            if($_right == $i) $_right --;
        } else {
            return '結果相加和爲0的組合之一爲:...';
        }
    }
}

5.基本完成了,就該想辦法優化了

暫時能想到的優化
(1) 有相同的數的話,就直接略過了,外層設置個has_read數組,外層a[i] 都填進去,當循環條件爲 in_array(a[i], $has_read) 的時候 continue;

結論

這類的題目,我覺得按照大體思路這麼跑,就可以,無非有序化,簡單化的事情,後面這種題萬變也不離其宗,無非是這幾個數的三次冪啊,求幾個數的積啊之類的。

你還有更好的解法嗎?或者有什麼有意思的題目,歡迎分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章