小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Two Sum 問(wèn)題的核心思想

 華府九五二七 2019-11-15

Two Sum 系列問(wèn)題在 LeetCode 上有好幾道,這篇文章就挑出有代表性的兩道,介紹一下這種問(wèn)題怎么解決。

TwoSum I

這個(gè)問(wèn)題的最基本形式是這樣:給你一個(gè)數(shù)組和一個(gè)整數(shù)target,可以保證數(shù)組中存在兩個(gè)數(shù)的和為target,請(qǐng)你返回這兩個(gè)數(shù)的索引。

比如輸入nums = [3,1,3,6],target = 6,算法應(yīng)該返回?cái)?shù)組[0,2],因?yàn)?3 + 3 = 6。

這個(gè)問(wèn)題如何解決呢?首先最簡(jiǎn)單粗暴的辦法當(dāng)然是窮舉了:

這個(gè)解法非常直接,時(shí)間復(fù)雜度 O(N^2),空間復(fù)雜度 O(1)。

更好一點(diǎn)的解法,可以通過(guò)一個(gè)哈希表減少時(shí)間復(fù)雜度:

這樣,由于哈希表的查詢時(shí)間為 O(1),算法的時(shí)間復(fù)雜度降低到 O(N),但是需要 O(N) 的空間復(fù)雜度來(lái)存儲(chǔ)哈希表。不過(guò)綜合來(lái)看,是要比暴力解法高效的。

我覺(jué)得 Two Sum 系列問(wèn)題就是想教我們?nèi)绾问褂霉1硖幚韱?wèn)題。我們接著往后看。

TwoSum II

稍微修改一下上面的問(wèn)題,要求我們?cè)O(shè)計(jì)一個(gè)類,擁有兩個(gè) API:

class TwoSum {
    // 向數(shù)據(jù)結(jié)構(gòu)中添加一個(gè)數(shù) number
    public void add(int number);
    // 尋找當(dāng)前數(shù)據(jù)結(jié)構(gòu)中是否存在兩個(gè)數(shù)的和為 value
    public boolean find(int value);
}

如何實(shí)現(xiàn)這兩個(gè) API 呢,我們可以仿照上一道題目,使用一個(gè)哈希表輔助find方法:

進(jìn)行find的時(shí)候有兩種情況,舉個(gè)例子:

情況一:如果連續(xù) add 了 [3,2,3,5],那么freq{3:2,2:1,5:1},執(zhí)行find(6),由于 3 出現(xiàn)了兩次,3 + 3 = 6,所以返回 true。

情況二:freq{3:2,2:1,5:1},執(zhí)行find(7),那么key為 2,other為 5 時(shí)算法可以返回 true。

除了上述兩種情況外,find只能返回 false 了。

對(duì)于這個(gè)解法的時(shí)間復(fù)雜度呢,add方法是 O(1),find方法是 O(N),空間復(fù)雜度為 O(N),和上一道題目比較類似。

但是對(duì)于 API 的設(shè)計(jì),是需要考慮現(xiàn)實(shí)情況的。比如說(shuō),我們?cè)O(shè)計(jì)的這個(gè)類,使用find方法非常頻繁,那么每次都要 O(N) 的時(shí)間,豈不是很浪費(fèi)費(fèi)時(shí)間嗎?對(duì)于這種情況,我們是否可以做些優(yōu)化呢?

是的,對(duì)于頻繁使用find方法的場(chǎng)景,我們可以進(jìn)行優(yōu)化。我們可以參考上一道題目的暴力解法,借助哈希集合來(lái)針對(duì)性優(yōu)化find方法:

這樣sum中就儲(chǔ)存了所有加入數(shù)字可能組成的和,每次find只要花費(fèi) O(1) 的時(shí)間在集合中判斷一下是否存在就行了,顯然非常適合頻繁使用find的場(chǎng)景。

三、總結(jié)

對(duì)于 TwoSum 問(wèn)題,一個(gè)難點(diǎn)就是給的數(shù)組無(wú)序。對(duì)于一個(gè)無(wú)序的數(shù)組,我們似乎什么技巧也沒(méi)有,只能暴力窮舉所有可能。

一般情況下,我們會(huì)首先把數(shù)組排序再考慮雙指針技巧。TwoSum 啟發(fā)我們,HashMap 或者 HashSet 也可以幫助我們處理無(wú)序數(shù)組相關(guān)的簡(jiǎn)單問(wèn)題。

另外,設(shè)計(jì)的核心在于權(quán)衡,利用不同的數(shù)據(jù)結(jié)構(gòu),可以得到一些針對(duì)性的加強(qiáng)。

最后,如果 TwoSum I 中給的數(shù)組是有序的,應(yīng)該如何編寫(xiě)算法呢?答案很簡(jiǎn)單,前文 雙指針技巧匯總 寫(xiě)過(guò):

int[] twoSum(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left < right) {
        int sum = nums[left] + nums[right];
        if (sum == target) {
            return new int[]{left, right};
        } else if (sum < target) {
            left++; // 讓 sum 大一點(diǎn)
        } else if (sum > target) {
            right--; // 讓 sum 小一點(diǎn)
        }
    }
    // 不存在這樣兩個(gè)數(shù)
    return new int[]{-1, -1};

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多