午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

LeetCode刷題實(shí)戰(zhàn)1:在數(shù)組上遍歷出花樣

 程序IT圈 2023-07-27 發(fā)布于福建
算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎(chǔ)知識(shí)和業(yè)務(wù)邏輯面試+算法面試。所以,為了提高大家的算法能力,這個(gè)公眾號(hào)后續(xù)每天帶大家做一道算法題,題目就從LeetCode上面選 !

廢話不多說,讓我們一起來看看題目吧。

Given an array of integers, return indices of the two numbers such that they add up to a specific target. 

You may assume that each input would have exactly one solution, and you may not use the same element twice.

https:///problems/two-sum/

翻譯

給定一個(gè)全是int的數(shù)組和一個(gè)整數(shù)target,要求返回兩個(gè)下標(biāo),使得數(shù)組當(dāng)中這兩個(gè)下標(biāo)對(duì)應(yīng)的和等于target。

你可以假設(shè)一定值存在一個(gè)答案,并且一個(gè)元素不能使用兩次。

解答

找兩個(gè)數(shù)和等于target,第一反應(yīng)就是暴力枚舉。假設(shè)數(shù)組長(zhǎng)度是n,那么一個(gè)

雙重循環(huán)就可以搞定。用Python的話,分分鐘就可以寫出代碼。

for i in range(len(array)):    for j in range(len(array)):        if array[i] + array[j] == target:            return [i, j]

這樣做當(dāng)然是正確的,但顯然不是最好的答案。根據(jù)經(jīng)驗(yàn),一般情況下O(n2)的算法都不是最優(yōu)解。

  引入map  


如果你熟悉C++ STL或者其他語(yǔ)言工具庫(kù)的用法,想必應(yīng)該很容易想到可以使用map。map是一個(gè)非常常用的容器,用來存儲(chǔ)key-value格式的數(shù)據(jù)對(duì)。

在這道題當(dāng)中,我們可以將元素和它在數(shù)組當(dāng)中對(duì)應(yīng)的下標(biāo)存儲(chǔ)進(jìn)map當(dāng)中。也就是說我們把所有數(shù)據(jù)對(duì)應(yīng)的下標(biāo)存儲(chǔ)好了之后,我們?cè)诒闅v的時(shí)候,就可以去掉j那一重循環(huán),而直接判斷target?a[j]在不在map當(dāng)中即可。


我們繼續(xù)寫出偽代碼:

for i in range(len(array)):    map[array[i]] = i;    if target - array[i] in map:        return [i, map[target - array[i]]]

這個(gè)算法看起來沒什么問題,但是如果你這么寫出代碼來提交一定過不了。

因?yàn)橛幸环N隱藏的情況沒有考慮到,一般我們會(huì)把這種隱藏的不容易想到的情況稱作“Trick”,可以看做是出題人使用的詭計(jì)。

題目當(dāng)中說了,同一個(gè)元素不能使用兩次,但是并沒有說數(shù)組當(dāng)中沒有重復(fù)的元素。map的使用有一個(gè)限制,就是不能有key值相同的元素。如果數(shù)組當(dāng)中存在重復(fù)的元素,那么后面讀到的數(shù)據(jù)會(huì)覆蓋前面的。覆蓋會(huì)產(chǎn)生什么問題呢?會(huì)導(dǎo)致我們沒有辦法判斷元素出現(xiàn)的次數(shù)。

舉個(gè)例子,比如:target=6, array=[3, 3]

由于我們使用了map,我們?cè)谟涗浵碌诙€(gè)3的時(shí)候,就會(huì)損失第一個(gè)3的信息。這樣我們就會(huì)錯(cuò)過答案,不過這個(gè)問題也并不是不能解決,我們可以用一個(gè)標(biāo)記記錄一下,是否有重復(fù)的數(shù)字或者是重復(fù)的數(shù)字是什么。不過這并不是完美的解決方案,我們沒有想到完美解法,是因?yàn)橛幸粋€(gè)潛在的條件被我們忽略了。

這個(gè)條件就是加法的交換律,也就是說a+b=target,那么b+a也應(yīng)該等于target。這當(dāng)然是一個(gè)廢話,但如果a和b之間存在順序的話就不一樣了。如果a的順序在b前面,那么我們應(yīng)該通過a去找b呢,還是應(yīng)該通過b去找a?

當(dāng)然是通過b去找a,因?yàn)閍在b之前,我們可以利用之前已經(jīng)遍歷過的信息查找。如果通過a去找b,那么我們需要再開辟一個(gè)循環(huán)遍歷。

想明白了這點(diǎn),剩下的就簡(jiǎn)單了。

假設(shè)數(shù)組array一共有n個(gè)元素,分別是a0,a1,?,an?1。我們用一個(gè)map存儲(chǔ)之前出現(xiàn)過的元素的下標(biāo),當(dāng)我們遍歷到i的時(shí)候,我們只需要判斷target?ai在不在map當(dāng)中即可。

因?yàn)榧僭O(shè)存在ai+aj=target,i<j。當(dāng)我們指針遍歷到i的時(shí)候找不出答案,因?yàn)?span role="textbox" aria-readonly="true" style="display: inline;line-height: normal;word-spacing: normal;overflow-wrap: normal;float: none;direction: ltr;max-width: none;max-height: none;min-width: 0px;min-height: 0px;border-width: 0px;border-style: initial;border-color: initial;">aj的值還沒有出現(xiàn)在map中。但是當(dāng)我們遍歷到j(luò)的時(shí)候,一定可以找到答案,因?yàn)?span role="textbox" aria-readonly="true" style="display: inline;line-height: normal;word-spacing: normal;overflow-wrap: normal;float: none;direction: ltr;max-width: none;max-height: none;min-width: 0px;min-height: 0px;border-width: 0px;border-style: initial;border-color: initial;">ai已經(jīng)出現(xiàn)過了。

通過利用加法交換律以及元素出現(xiàn)的先后順序,再結(jié)合map,我們只需要一次遍歷就可以找到答案。就算出現(xiàn)重復(fù)元素,也沒有關(guān)系,因?yàn)槲覀兪窍扰袛啻娌淮嬖?,再更新map。

最后,附上偽代碼:

for i in array.length:    if target - array[i] in map:        return i, map[target - array[i]]    else:        map.put(array[i], i)

這題本身并不難解,用到的知識(shí)也平淡無奇,不過要想能琢磨出其中的trick,并想到解法,并不容易,需要基于充分的思考和理解。

簡(jiǎn)單題也能有所收獲,祝大家刷題愉快。

點(diǎn)個(gè)"
在看
",告訴我你曾來過
 

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

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

    類似文章 更多