从喧闹与富有中搞懂搜索和拓扑
前言
大家好我是bigsai。
今天給大家分享一個(gè)非常有趣的面試題,通過(guò)這個(gè)問(wèn)題你可能會(huì)對(duì)某些情況下,搜索和拓?fù)?/strong>有一定的認(rèn)識(shí),一個(gè)問(wèn)題,既可以用搜索來(lái)處理,用記憶化搜索優(yōu)化,也可以用拓?fù)渑判騺?lái)解決。
題目為力扣851,喧鬧和富有 ,題意為
有一組 n 個(gè)人作為實(shí)驗(yàn)對(duì)象,從 0 到 n - 1 編號(hào),其中每個(gè)人都有不同數(shù)目的錢(qián),以及不同程度的安靜值(quietness)。為了方便起見(jiàn),我們將編號(hào)為 x 的人簡(jiǎn)稱為 "person x "。
給你一個(gè)數(shù)組 richer ,其中 richer[i] = [ai, bi] 表示 person ai 比 person bi 更有錢(qián)。另給你一個(gè)整數(shù)數(shù)組 quiet ,其中 quiet[i] 是 person i 的安靜值。richer 中所給出的數(shù)據(jù) 邏輯自洽(也就是說(shuō),在 person x 比 person y 更有錢(qián)的同時(shí),不會(huì)出現(xiàn) person y 比 person x 更有錢(qián)的情況 )。
現(xiàn)在,返回一個(gè)整數(shù)數(shù)組 answer 作為答案,其中 answer[x] = y 的前提是,在所有擁有的錢(qián)肯定不少于 person x 的人中,person y 是最安靜的人(也就是安靜值 quiet[y] 最小的人)
理解題意
這個(gè)問(wèn)題其實(shí)要理解題意還是需要一點(diǎn)時(shí)間的,我也讀了不少時(shí)間才搞明白(原諒我語(yǔ)文很差)。
題目大概的意思是:題目告訴你一堆關(guān)系,對(duì)就是誰(shuí)比誰(shuí)有錢(qián)。
舉個(gè)例子,你們宿舍4個(gè)人,不是誰(shuí)跟誰(shuí)關(guān)系都很好,有的私交不一定很深。
你是江蘇某窮鄉(xiāng)僻壤來(lái)的,為人很害羞不跟人說(shuō)話,只跟省會(huì)南京的一個(gè)舍友聊天,南京舍友跟你說(shuō)他是南京城里土著你就知道他比你有錢(qián)了……。南京舍友跟北京舍友聊天得知北京舍友四合院臥槽北京舍友有錢(qián),南京舍友跟上海舍友聊天得知上海舍友有好幾套房肯定比它有錢(qián),但北上兩舍友性格不合沒(méi)聊過(guò)家里啥情況互相不敢猜測(cè)誰(shuí)比誰(shuí)有錢(qián)。
所以你們宿舍形成這樣一個(gè)關(guān)系:
但是這里面有兩種評(píng)判標(biāo)準(zhǔn)構(gòu)造這個(gè)邏輯,一個(gè)是比我窮,一個(gè)是比我有錢(qián),究竟怎么使用我們繼續(xù)看題意。
題目說(shuō)每個(gè)人有個(gè)低調(diào)值(簡(jiǎn)單說(shuō)啦),然后每個(gè)人要找到這個(gè)邏輯中比自己有錢(qián)(包括自己)最低調(diào)的人。
比我有錢(qián)的角度
如果從比我有錢(qián)角度出發(fā), 那么每次都要進(jìn)行搜索,根據(jù)這個(gè)順序結(jié)構(gòu)找到比我有錢(qián)的最低調(diào)的人,比如看最上面從你出發(fā),找南京知道的最低調(diào)的有錢(qián)人。但是這個(gè)步驟使用搜索遞歸,這4個(gè)人你看不出來(lái),如果說(shuō)你們宿舍5個(gè)人,有個(gè)山溝溝的舍友比你還窮,他搜索時(shí)候:你、南京舍友、{北京,上海搜索分叉}。然后到你的時(shí)候,又是:南京舍友、{北京,上海搜索分叉},這樣重復(fù)計(jì)算效率很低啊。這就可以用記憶化搜索,搜過(guò)一遍記下來(lái)。
代碼我沒(méi)寫(xiě),沒(méi)用這個(gè)方法。因?yàn)樗阉魇菑纳俚那闆r搜索更多未知的內(nèi)容,會(huì)有比較多的重復(fù)計(jì)算,所以記憶化搜索就比較重要了。
比我窮的角度
從比我窮的角度來(lái)看,我是可以直接改變直接比我窮的那個(gè)人的低調(diào)值指向的,這個(gè)比我窮的角度就是拓?fù)渑判?/strong>了,例如上面北京舍友或者上海舍友肯定第一個(gè)。
假如北京舍友第一個(gè),拓?fù)湔业奖任腋F的南京舍友,然后看看我的低調(diào)值是不是比它的低,如果比他低,那么南京舍友低調(diào)值換成我的,并且低調(diào)指向編號(hào)是我。
然后上海舍友第二個(gè),雖然你被北京舍友摩擦過(guò)但是不影響,上海舍友希望將南京舍友從北京小伙手中奪過(guò)來(lái)(有可能南京小伙本身非常低調(diào)沒(méi)被感染),然后上海小伙三顧茅廬低調(diào)值比被感染過(guò)得南京舍友還低,那南京舍友還等什么,直接低調(diào)值跟隨上海舍友,低調(diào)值指向上海舍友位置。
然后第三個(gè)南京舍友,他此時(shí)低調(diào)值非常低了(因?yàn)榍懊姹鄙虾退约喝齻€(gè)最低就是他),如果他低調(diào)值比你低,你低調(diào)值變成他一樣,然后指向他指向的對(duì)應(yīng)位置。
這就是一個(gè)拓?fù)渑判虻倪^(guò)程,這里面幾個(gè)細(xì)節(jié):
低調(diào)值改變:你可能直接支配比你窮的人,你一旦支配比你窮的,比你窮還窮的那些人很可能也被你支配,你的很低的低調(diào)值和位置需要被傳遞下去,所以需要一些標(biāo)記。
附上代碼:
class Solution {public int[] loudAndRich(int[][] richer, int[] quiet) {int len=quiet.length;List<Integer> next[]=new ArrayList[len];//記錄指向的集合int inDegree[]=new int[len];//記錄入度int value[]=new int[len];for(int i=0;i<len;i++){next[i]=new ArrayList<>();value[i]=i;}for(int i=0;i<richer.length;i++){int rich=richer[i][0];int poor=richer[i][1];next[rich].add(poor);inDegree[poor]++;}Queue<Integer>queue=new ArrayDeque<>();for(int i=0;i<len;i++){if(inDegree[i]==0)queue.add(i);}while (!queue.isEmpty()){int rich=queue.poll();for(int poor:next[rich]){inDegree[poor]--;if(quiet[rich]<quiet[poor]){quiet[poor]=quiet[rich];value[poor]=value[rich];}if(inDegree[poor]==0){queue.add(poor);}}}return value;} }這樣,這個(gè)問(wèn)題就解決啦。
好啦,平安夜圣誕快樂(lè),我是bigsai,我們下次再見(jiàn)!
總結(jié)
以上是生活随笔為你收集整理的从喧闹与富有中搞懂搜索和拓扑的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 字节面试现场,问我如何高效设计一个LRU
- 下一篇: 字节面试必须拿下的十道算法题,你会几道?