IT技術(shù)小屋

          秋風(fēng)秋雨,皆入我心

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            38 隨筆 :: 1 文章 :: 19 評(píng)論 :: 0 Trackbacks

          2014年1月5日 #

          本文介紹了包括 Python、Java、Haskell等在內(nèi)的一系列編程語(yǔ)言的深度學(xué)習(xí)庫(kù)。

          Python
          • Theano是一種用于使用數(shù)列來(lái)定義和評(píng)估數(shù)學(xué)表達(dá)的 Python 庫(kù)。它可以讓 Python 中深度學(xué)習(xí)算法的編寫更為簡(jiǎn)單。很多其他的庫(kù)是以 Theano 為基礎(chǔ)開(kāi)發(fā)的。
          • Caffe是一種以表達(dá)清晰、高速和模塊化為理念建立起來(lái)的深度學(xué)習(xí)框架。它是由伯克利視覺(jué)和學(xué)習(xí)中心(BVLC)和網(wǎng)上社區(qū)貢獻(xiàn)者共同開(kāi)發(fā)的。谷歌的 DeepDream 人工智能圖像處理程序正是建立在 Caffe 框架之上。這個(gè)框架是一個(gè) BSD 許可的帶有 Python 接口的 C++庫(kù)。
          • nolearn包含大量其他神經(jīng)網(wǎng)絡(luò)庫(kù)中的包裝器和抽象(wrappers and abstractions),其中最值得注意的是 Lasagne,其中也包含一些機(jī)器學(xué)習(xí)的實(shí)用模塊。
          • Genism是一個(gè)部署在 Python 編程語(yǔ)言中的深度學(xué)習(xí)工具包,用于通過(guò)高效的算法處理大型文本集。
          • Chainer連接深度學(xué)習(xí)中的算法與實(shí)現(xiàn),它強(qiáng)勁、靈活而敏銳,是一種用于深度學(xué)習(xí)的靈活的框架。
          • deepnet是一種基于 GPU 的深度學(xué)習(xí)算法的 Python 實(shí)現(xiàn),比如:前饋神經(jīng)網(wǎng)絡(luò)、受限玻爾茲曼機(jī)、深度信念網(wǎng)絡(luò)、自編碼器、深度玻爾茲曼機(jī)和卷積神經(jīng)網(wǎng)絡(luò)。
          • Hebel是一個(gè)在 Python 中用于帶有神經(jīng)網(wǎng)絡(luò)的深度學(xué)習(xí)的庫(kù),它通過(guò) PyCUDA 使用帶有 CUDA 的 GPU 加速。它可實(shí)現(xiàn)大多數(shù)目前最重要的神經(jīng)網(wǎng)絡(luò)模型,提供了多種不同的激活函數(shù)和訓(xùn)練方式,如動(dòng)量,Nesterov 動(dòng)量,退出(dropout)和 前期停止(early stopping)。
          • CXXNET是一種快速,簡(jiǎn)明的分布式深度學(xué)習(xí)框架,它以 MShadow 為基礎(chǔ)。它是輕量級(jí)可擴(kuò)展的 C++/CUDA 神經(jīng)網(wǎng)絡(luò)工具包,同時(shí)擁有友好的 Python/Matlab 界面,可供機(jī)器學(xué)習(xí)的訓(xùn)練和預(yù)測(cè)使用。
          • DeepPy是一種建立在 Mumpy 之上的 Python 化的深度學(xué)習(xí)框架。
          • DeepLearning是一個(gè)用 C++和 Python 開(kāi)發(fā)的深度學(xué)習(xí)庫(kù)。
          C++
          • eblearn是一個(gè)機(jī)器學(xué)習(xí)的開(kāi)源 C++庫(kù),由紐約大學(xué)機(jī)器學(xué)習(xí)實(shí)驗(yàn)室的 Yann LeCun 牽頭研發(fā)。尤其是,按照 GUI、演示和教程來(lái)部署的帶有基于能量的模型的卷積神經(jīng)網(wǎng)絡(luò)。
          • SINGA被設(shè)計(jì)用來(lái)進(jìn)行已有系統(tǒng)中分布式訓(xùn)練算法的普通實(shí)現(xiàn)。它由 Apache Software Foundation 提供支持。
          Java
          • N-Dimensional Arrays for Java (ND4J)是一種為 JVM 設(shè)計(jì)的科學(xué)計(jì)算庫(kù)。它們被應(yīng)用在生產(chǎn)環(huán)境中,這就意味著路徑被設(shè)計(jì)成可以最小的 RAM 內(nèi)存需求來(lái)快速運(yùn)行。
          • Deeplearning4j是第一個(gè)為 Java 和 Scala 編寫的消費(fèi)級(jí)開(kāi)元分布式深度學(xué)習(xí)庫(kù)。它被設(shè)計(jì)成在商業(yè)環(huán)境中使用,而非研究工具。
          • Encog是一種先進(jìn)的機(jī)器學(xué)習(xí)框架,支持支持向量機(jī)(Support Vector Machines),人工神經(jīng)網(wǎng)絡(luò)(Artificial Neural Networks),基因編程(Genetic Programming),貝葉斯網(wǎng)絡(luò)(Bayesian Networks),隱馬爾科夫模型(Hidden Markov Models)和 遺傳算法(Genetic Algorithms)。
          Lua
          • Torch是一種科學(xué)計(jì)算框架,可支持多種計(jì)算機(jī)學(xué)習(xí)算法。
          Haskell
          • DNNGraph是一個(gè)用 Haskell 編寫的深度神經(jīng)網(wǎng)絡(luò)生成 DSL。
          .NET
          • Accord.NET是一種.NET 機(jī)器學(xué)習(xí)框架,包含聲音和圖像處理庫(kù),它完全由 C# 編寫。它是一種為開(kāi)發(fā)生產(chǎn)級(jí)的計(jì)算機(jī)視覺(jué)、計(jì)算機(jī)聽(tīng)覺(jué)、信號(hào)處理和統(tǒng)計(jì)應(yīng)用而設(shè)計(jì)的完整框架。
          R
          • darch包可以用于建立多層神經(jīng)網(wǎng)絡(luò)(深層結(jié)構(gòu))。其中的訓(xùn)練方式包括使用對(duì)比發(fā)散法進(jìn)行提前訓(xùn)練,或使用通常的訓(xùn)練方法(如反向傳播和共軛梯度)進(jìn)行一些微調(diào)。
          • deepnet實(shí)現(xiàn)了一些深度學(xué)習(xí)架構(gòu)和神經(jīng)網(wǎng)絡(luò)算法,包括 BP、RBM、DBN、深度自編碼器等等。

          posted @ 2016-11-13 00:45 Meng Lee 閱讀(455) | 評(píng)論 (0)編輯 收藏

          今天,終于有時(shí)間靜下心來(lái)回顧過(guò)去兩年來(lái)所做的事情,感慨萬(wàn)千,一時(shí)之間竟不知從何說(shuō)起。兩年以來(lái),遇到的困難著實(shí)不少,但每每遭遇挫折與不順之后,卻往往能柳暗花明,遇到新的轉(zhuǎn)機(jī),讓我真真切切地感受到了功夫不負(fù)有心人這句話的含意。

          一、為什么要出國(guó)
          其實(shí),之前從來(lái)沒(méi)有考慮過(guò)要出國(guó),更沒(méi)有想過(guò)能直接出國(guó)工作。回想一下,這個(gè)決定的做出,多半還是緣于自己骨子里的不安分。我從很大程度上來(lái)說(shuō)是一個(gè)閑不住的人,從小學(xué)、中學(xué)、大學(xué)到研究生,我?guī)缀趺刻於加忻鞔_的目標(biāo)。然而,2013年從公司到事業(yè)單位工作以后,我的生活發(fā)生了巨大地轉(zhuǎn)變。簡(jiǎn)單的工作、空洞的公文、無(wú)聊的活動(dòng)占據(jù)了我全部的工作任務(wù)。有段時(shí)間幾乎天天寫材料搞活動(dòng)。領(lǐng)導(dǎo)經(jīng)常夸我材料寫得又快又好,活動(dòng)也搞得有聲有色,心里感覺(jué)很有成就感。然而,時(shí)間一長(zhǎng),逐漸發(fā)現(xiàn)那些公文永遠(yuǎn)是一個(gè)套路,以至于我分門別類,摸索出了幾個(gè)萬(wàn)能模板。而活動(dòng)則千篇一律,讓人疲于應(yīng)付。我甚至可以看到六十歲退休時(shí)我在干什么,于是一陣恐懼感常常會(huì)莫名襲來(lái),因?yàn)槲也话卜帧⒉粷M足于此。我不能放棄所學(xué)所長(zhǎng),我不能庸庸碌碌在這里度過(guò)未來(lái)的幾十年,我還有夢(mèng)想,我還要登高看世界。為了這個(gè),我走過(guò)了不平凡的兩年。

          二、如何出國(guó)
          對(duì)于普通人來(lái)說(shuō),出國(guó)大致有三條路。
          第一條路是申請(qǐng)去國(guó)外留學(xué),取得學(xué)位之后以應(yīng)屆畢業(yè)生的身份找工作,然后留在國(guó)外生活。這是一條比較穩(wěn)妥、簡(jiǎn)便的路,走這條路的人最多。
          第二條路是先進(jìn)入跨國(guó)公司的中國(guó)分公司工作一段時(shí)間,然后找機(jī)會(huì)外派到國(guó)外總部工作。走這條路的要求比較多,首先要能夠進(jìn)入比較大的跨國(guó)公司工作,其次這個(gè)公司愿意將中國(guó)員工transfer到國(guó)外,同時(shí)還要外國(guó)總部有部門愿意接收你,所以還是需要一些運(yùn)氣。但是,如果成功,好處也顯而易見(jiàn)。省去了讀書的時(shí)間和學(xué)費(fèi),降低了家庭負(fù)擔(dān),對(duì)于家境一般的人是非常好的選擇。
          第三條路是直接參加外國(guó)公司的面試,通過(guò)之后直接去國(guó)外工作。這條路要求最高,需要通過(guò)外國(guó)公司嚴(yán)格的面試,另外還要能夠成功取得簽證(美國(guó)工作簽證就需要抽簽)。因此,走這條路更需要實(shí)力、機(jī)遇和運(yùn)氣。
          鑒于第三條路非常難走,為了保證成功,我選擇了同時(shí)申請(qǐng)學(xué)校和參加外國(guó)公司面試的辦法,這也注定了我將付出更多的艱苦努力。

          三、申請(qǐng)學(xué)校
          申請(qǐng)學(xué)校從準(zhǔn)備到最終完成,我大概用了一年時(shí)間。其間參加了三次GRE和一次托福考試。回想準(zhǔn)備的過(guò)程,最大的敵人就是自己,最重要的法寶就是堅(jiān)持堅(jiān)持再堅(jiān)持。記得第一次考GRE沒(méi)有取得理想的成績(jī),因?yàn)槭堑谝淮螀⒓佑⒄Z(yǔ)考試,心情非常失落。幸虧當(dāng)時(shí)有女朋友(現(xiàn)在的老婆)的鼓勵(lì),我繼續(xù)復(fù)習(xí)沒(méi)有放棄。經(jīng)過(guò)一個(gè)月的復(fù)習(xí),取得了非常不錯(cuò)的托福成績(jī)。記得托福出成績(jī)的那天,我緊張得不敢查,點(diǎn)開(kāi)頁(yè)面的那一刻,我都不敢相信居然能有這么不錯(cuò)的成績(jī)。特別是聽(tīng)力,考試的時(shí)候覺(jué)得好幾個(gè)都沒(méi)有聽(tīng)清楚,最后居然有27分,真是不可思議,可見(jiàn)功夫不負(fù)有心人,付出總有回報(bào)的。
          有了英語(yǔ)成績(jī)之后,就是撰寫申請(qǐng)文書。這方面我完全沒(méi)有經(jīng)驗(yàn),所有的信息全部是通過(guò)一畝三分地論壇獲得的。這個(gè)論壇信息非常豐富,基本上所有申請(qǐng)相關(guān)的內(nèi)容都有涉及。我每天都會(huì)花一些時(shí)間瀏覽別人的帖子,為自己定位選校,找文書靈感等等。非常感謝我的本科和研究生導(dǎo)師,還有蔣志誠(chéng)為我遞推薦信,沒(méi)有你們的幫助,我不可能完成申請(qǐng)工作。
          最后,我申請(qǐng)了美國(guó)和加拿大的十五所學(xué)校的計(jì)算機(jī)專業(yè)的研究生,拿到了CMU、USC和多倫多大學(xué)的offer。其中,CMU的Data Science program應(yīng)該是世界數(shù)一數(shù)二的,錄取率非常低,畢業(yè)后的去向也非常好,大多數(shù)都可以進(jìn)入美國(guó)一流公司工作。多大也是加拿大排名第一的學(xué)校,計(jì)算機(jī)的就業(yè)也非常好。

          四、Facebook的面試
          參加Facebook的面試也完全是無(wú)意的,在Linkedin上收到了Facebook HR的邀請(qǐng)信,于是也沒(méi)有怎么準(zhǔn)備就做了電面,居然反饋非常好,馬上就給我安排了onsite面試,地點(diǎn)是印度的海得拉巴。但是,始終是沒(méi)有做什么準(zhǔn)備,而且和谷歌不一樣的是,HR辦事效率實(shí)在太高,每一輪間隔都非常短,導(dǎo)致我根本沒(méi)有時(shí)間熱身一下,連leetcode都沒(méi)有做過(guò)就匆匆參加面試了,最終沒(méi)有如愿通過(guò)面試。
          不過(guò),這次面試還是很有收獲。第一次出國(guó),第一次參加美國(guó)公司全英文面試,學(xué)到了太多,積累了經(jīng)驗(yàn),可以說(shuō)如果沒(méi)有Facebook的失敗,我是不可能進(jìn)入谷歌的。

          五、Google的面試
          參加谷歌的面試可以說(shuō)完全是老婆的慫恿。從印度參加完Facebook面試回來(lái)之后,我就開(kāi)始專心于學(xué)校申請(qǐng)了。但是,老婆建議我試試面一下Google。由于Facebook的失利和Google近乎苛刻的面試流程,我開(kāi)始是抗拒參加的。最后,在老婆的一再要求下,我終于找了一個(gè)在谷歌上海工作的師兄做了內(nèi)推。四月底我收到了谷歌北京HR的第一通電話,也正式拉開(kāi)了我為期一年的面試流程。
          和HR通電話不久,我進(jìn)行了第一次電話面試。谷歌的電話面試和Facebook差不多,就是面試官打過(guò)來(lái),把題目口述并且寫在Google Doc上,然后我把程序?qū)懺贕oogle Doc上。第一次電面的題目不難,但谷歌對(duì)代碼效率和清晰度的要求遠(yuǎn)遠(yuǎn)超出了我的想像。第一輪面得磕磕絆絆,但是幸好面試官是中國(guó)人,非常nice,沒(méi)有讓我fail。
          于是,我又被要求進(jìn)行第二次電面。期間由于面試官臨時(shí)有事爽約,我等了差不多一個(gè)月。但是,也就是這一個(gè)月,我努力做了一些準(zhǔn)備,雖然面試依舊不是十全十美,但是我還是有驚無(wú)險(xiǎn)地進(jìn)入到了onsite面試環(huán)節(jié)。
          雖然可以onsite面試了,但是我依舊對(duì)進(jìn)入谷歌不報(bào)任何希望,因?yàn)槲仪宄闹溃?/span>谷歌面試實(shí)在是太難了,onsite面試的挑戰(zhàn)將遠(yuǎn)遠(yuǎn)大于電面。因此,我去北京面試完全是想做一次免費(fèi)旅游。面試前一天還許久不見(jiàn)的萬(wàn)威夫婦吃飯,聊得很開(kāi)心,完全沒(méi)有把面試放在心上。
          也許是放松的原因,我前一天晚上睡得很好,第二天我精神非常好。
          不過(guò)谷歌畢竟是谷歌,面試第一輪一上來(lái)就給了我一個(gè)下馬威。一個(gè)coding題一個(gè)設(shè)計(jì)題,表面上很簡(jiǎn)單,但是做出來(lái)總是有這樣那樣的問(wèn)題,第一輪完了之后我基本打算回家了。
          但是,不知道為什么,從第二輪開(kāi)始,就越來(lái)越順利,coding做得非常好,基本上是一次寫完,沒(méi)有涂改,也沒(méi)有被面試官找到大的bug。突然之間,隱隱感覺(jué)出現(xiàn)了一絲希望。
          四輪過(guò)后,我結(jié)束了第一次onsite面試。但是,三天之后,我被告知由于設(shè)計(jì)題做得不好,我被要求進(jìn)行一次加面,地點(diǎn)在上海。于是,我又在上海做了一次面試,只有一個(gè)設(shè)計(jì)題。我感覺(jué)答得還可以,但是心情真的是忐忑不安,特別是接下來(lái)的一個(gè)禮拜,幾乎是坐立不安。
          記得是一個(gè)禮拜之后的禮拜五中午,我正做準(zhǔn)備主持下午的道德講堂,突然接到了一個(gè)010的電話,我知道是谷歌的電話。接通電話的那一刻,空氣都幾乎要凝固了,當(dāng)聽(tīng)到通過(guò)HC的消息時(shí),我激動(dòng)得不能自已。不可能完成的任務(wù)居然完成了,雖然不知道能不能去美國(guó)總部工作,但是能進(jìn)入谷歌已經(jīng)非常不容易了,而且谷歌非常鼓勵(lì)transfer去美國(guó)工作,因此機(jī)會(huì)還是很多的。
          然而,讓我沒(méi)有想到的是,接下來(lái)的team match卻異常艱難,陸陸續(xù)續(xù)幾個(gè)team都沒(méi)有成功match上。轉(zhuǎn)眼就到了2014年春季,半年的等待讓我對(duì)何時(shí)進(jìn)入谷歌非常悲觀,加上申請(qǐng)學(xué)校工作十分繁重,我基本沒(méi)有關(guān)注這個(gè)事情。
          就在我快要放棄的時(shí)候,拿到了美國(guó)一個(gè)公司的offer,他們答應(yīng)給我辦H1B簽證。于是,我把這個(gè)情況告訴了谷歌,要求他們盡快給找到team,不然我就去美國(guó)了。結(jié)果谷歌居然在三天之內(nèi)為我match上了英國(guó)office的一個(gè)team,讓人不得不感嘆還是要offer多才好啊!于是,我又經(jīng)過(guò)了近三個(gè)月的簽證辦理流程,終于要啟程赴英了。

          回顧兩年來(lái)的努力,終于要實(shí)現(xiàn)自己的夢(mèng)想了,感慨萬(wàn)千。在短短的人生中,能有這一段不尋常的經(jīng)歷,我覺(jué)得十分幸運(yùn)。展望未來(lái),我想讀萬(wàn)卷書不如行萬(wàn)里路,未來(lái)希望能夠利用在倫敦工作的機(jī)會(huì),盡量多去歐洲各國(guó)走走,豐富自己的閱歷,開(kāi)拓自己的眼界。

          最后要感謝老婆一直以來(lái)的支持和鼓勵(lì),你一直是我前進(jìn)的動(dòng)力;其次要感謝父母的不理解和不支持,你們的反對(duì)讓我更加完善了自己的計(jì)劃,逼著我找到了一條最好的出路;還要感謝師長(zhǎng)和朋友們的幫助,感謝楊老師和沈老師還有蔣志誠(chéng)不厭其煩地幫我遞推薦信,感謝萬(wàn)威夫婦多次在北京款待我,沒(méi)有你們的美食,我是不可能完成面試的;還有許多幫助過(guò)我的人,在這里就不能一一感謝了。
          posted @ 2014-06-13 02:00 Meng Lee 閱讀(1494) | 評(píng)論 (0)編輯 收藏

          算法很簡(jiǎn)單,核心思想是:對(duì)某個(gè)值A(chǔ)[i]來(lái)說(shuō),能trapped的最多的water取決于在i之前最高的值leftMostHeight[i]和在i右邊的最高的值rightMostHeight[i]。(均不包含自身)。如果min(left,right) > A[i],那么在i這個(gè)位置上能trapped的water就是min(left,right) – A[i]。
          有了這個(gè)想法就好辦了,第一遍從左到右計(jì)算數(shù)組leftMostHeight,第二遍從右到左計(jì)算rightMostHeight,在第二遍的同時(shí)就可以計(jì)算出i位置的結(jié)果了,而且并不需要開(kāi)空間來(lái)存放rightMostHeight數(shù)組。
          時(shí)間復(fù)雜度是O(n),只掃了兩遍。

           1 public class TrappingRainWater {
           2     public int trap(int A[], int n) {
           3         if (n <= 2)
           4             return 0;
           5 
           6         int[] lmh = new int[n];
           7         lmh[0] = 0;
           8         int maxh = A[0];
           9         for (int i = 1; i < n; ++i) {
          10             lmh[i] = maxh;
          11             if (maxh < A[i])
          12                 maxh = A[i];
          13         }
          14         int trapped = 0;
          15         maxh = A[n - 1];
          16         for (int i = n - 2; i > 0; --i) {
          17             int left = lmh[i];
          18             int right = maxh;
          19             int container = Math.min(left, right);
          20             if (container > A[i]) {
          21                 trapped += container - A[i];
          22             }
          23             if (maxh < A[i])
          24                 maxh = A[i];
          25         }
          26         return trapped;
          27     }
          28 }
          posted @ 2014-01-14 09:16 Meng Lee 閱讀(224) | 評(píng)論 (0)編輯 收藏

          The set [1,2,3,…,n] contains a total of n! unique permutations.
          By listing and labeling all of the permutations in order,
          We get the following sequence (ie, for n = 3):
          "123"
          "132"
          "213"
          "231"
          "312"
          "321"
          Given n and k, return the kth permutation sequence.
          Note: Given n will be between 1 and 9 inclusive.

          這道題其實(shí)有很強(qiáng)的規(guī)律可循。首先,n個(gè)元素的排列總數(shù)是n!。在下面的分析中,讓k的范圍是0 <= k < n!。(題目代碼實(shí)際上是1<=k<=n!)
          可以看到一個(gè)規(guī)律,就是這n!個(gè)排列中,第一位的元素總是(n-1)!一組出現(xiàn)的,也就說(shuō)如果p = k / (n-1)!,那么排列的最開(kāi)始一個(gè)元素一定是arr[p]。
          這個(gè)規(guī)律可以類推下去,在剩余的n-1個(gè)元素中逐漸挑選出第二個(gè),第三個(gè),...,到第n個(gè)元素。程序就結(jié)束。
           1 /**
           2  * The set [1,2,3,…,n] contains a total of n! unique permutations.
           3  * 
           4  * By listing and labeling all of the permutations in order, We get the
           5  * following sequence (ie, for n = 3):
           6  * 
           7  * "123" "132" "213" "231" "312" "321" Given n and k, return the kth permutation
           8  * sequence.
           9  * 
          10  * Note: Given n will be between 1 and 9 inclusive.
          11  * 
          12  */
          13 
          14 public class PermutationSequence {
          15     public String getPermutation(int n, int k) {
          16         char[] arr = new char[n];
          17         int pro = 1;
          18         for (int i = 0; i < n; ++i) {
          19             arr[i] = (char) ('1' + i);
          20             pro *= (i + 1);
          21         }
          22         k = k - 1;
          23         k %= pro;
          24         pro /= n;
          25         for (int i = 0; i < n - 1; ++i) {
          26             int selectI = k / pro;
          27             k = k % pro;
          28             pro /= (n - i - 1);
          29             int temp = arr[selectI + i];
          30             for (int j = selectI; j > 0; --j) {
          31                 arr[i + j] = arr[i + j - 1];
          32             }
          33             arr[i] = (char) temp;
          34         }
          35         return String.valueOf(arr);
          36     }
          37 }
          38 
          posted @ 2014-01-07 16:06 Meng Lee 閱讀(451) | 評(píng)論 (0)編輯 收藏

          Lowest Common Ancestor of a Binary Search Tree (BST)
          Given a binary search tree (BST), find the lowest common ancestor of two given nodes in the BST.
                 _______6______
                /              \
             ___2__          ___8__
            /      \        /      \
            0      _4       7       9
                  /  \
                  3   5
          Using the above tree as an example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. 
          But how about LCA of nodes 2 and 4? Should it be 6 or 2?
          According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between 
          two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a 
          node to be a descendant of itself).” Since a node can be a descendant of itself, the LCA of 2 and 
          4 should be 2, according to this definition.
          Hint:
          A top-down walk from the root of the tree is enough.

           1 public class LowestCommonAncestorOfaBinarySearchTree {
           2     public TreeNode LCA(TreeNode root, TreeNode p, TreeNode q) {
           3         if (root == null || p == null || q == null)
           4             return null;
           5         if (Math.max(p.val, q.val) < root.val)
           6             return LCA(root.left, p, q);
           7         if (Math.min(p.val, q.val) > root.val)
           8             return LCA(root.right, p, q);
           9         return root;
          10     }
          11 }


          Given a binary tree, find the lowest common ancestor of two given nodes in the tree.
           
           
                  _______3______
                 /              \
              ___5__          ___1__
             /      \        /      \
            6      _2       0       8
                   /  \
                   7   4
          If you are not so sure about the definition of lowest common ancestor (LCA), please refer to my previous 
          post: Lowest Common Ancestor of a Binary Search Tree (BST) or the definition of LCA here. Using the tree 
          above as an example, the LCA of nodes 5 and 1 is 3. Please note that LCA for nodes 5 and 4 is 5.
           
          Hint:
          Top-down or bottom-up? Consider both approaches and see which one is more efficient.
           1 public class LowestCommonAncestorOfBinaryTree {
           2     public TreeNode LCA(TreeNode root, TreeNode p, TreeNode q) {
           3         if (root == null)
           4             return null;
           5         if (root == p || root == q)
           6             return root;
           7         TreeNode left = LCA(root.left, p, q);
           8         TreeNode right = LCA(root.right, p, q);
           9         if (left != null && right != null)
          10             return root;
          11         return left != null ? left : right;
          12     }
          13 }
          posted @ 2014-01-06 09:32 Meng Lee 閱讀(346) | 評(píng)論 (0)編輯 收藏

          Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
          Below is one possible representation of s1 = "great":
              great
             /    \
            gr    eat
           / \    /  \
          g   r  e   at
                     / \
                    a   t
          To scramble the string, we may choose any non-leaf node and swap its two children.
          For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".
              rgeat
             /    \
            rg    eat
           / \    /  \
          r   g  e   at
                     / \
                    a   t
          We say that "rgeat" is a scrambled string of "great".
          Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".
              rgtae
             /    \
            rg    tae
           / \    /  \
          r   g  ta  e
                 / \
                t   a
          We say that "rgtae" is a scrambled string of "great".
          Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

           1 public class ScrambleString {
           2     public boolean isScramble(String s1, String s2) {
           3         if (s1.length() != s2.length())
           4             return false;
           5         if (s1.equals(s2))
           6             return true;
           7 
           8         int[] A = new int[26];
           9         for (int i = 0; i < s1.length(); i++) {
          10             ++A[s1.charAt(i) - 'a'];
          11         }
          12 
          13         for (int j = 0; j < s2.length(); j++) {
          14             --A[s2.charAt(j) - 'a'];
          15         }
          16 
          17         for (int k = 0; k < 26; k++) {
          18             if (A[k] != 0)
          19                 return false;
          20         }
          21 
          22         for (int i = 1; i < s1.length(); i++) {
          23             boolean result = isScramble(s1.substring(0, i), s2.substring(0, i))
          24                     && isScramble(s1.substring(i), s2.substring(i));
          25             result = result
          26                     || (isScramble(s1.substring(0, i),
          27                             s2.substring(s2.length() - i, s2.length())) && isScramble(
          28                             s1.substring(i), s2.substring(0, s2.length() - i)));
          29             if (result)
          30                 return true;
          31         }
          32         return false;
          33     }
          34 }
          posted @ 2014-01-05 12:33 Meng Lee 閱讀(222) | 評(píng)論 (0)編輯 收藏

          Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
          Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
          The largest rectangle is shown in the shaded area, which has area = 10 unit.
          For example,
          Given height = [2,1,5,6,2,3],
          return 10.

          本題需要使用棧維護(hù)一個(gè)高度單調(diào)遞增的序列下標(biāo),如果遇到一個(gè)元素比當(dāng)前棧頂元素高度小,那么出棧,并計(jì)算當(dāng)前最大面積。如果棧為空,需要特殊考慮。
           1 public class LargestRectangleinHistogram {
           2     public int largestRectangleArea(int[] height) {
           3         Stack<Integer> stack = new Stack<Integer>();
           4         int i = 0;
           5         int maxArea = 0;
           6         int[] h = new int[height.length + 1];
           7         h = Arrays.copyOf(height, height.length + 1);
           8         while (i < h.length) {
           9             if (stack.isEmpty() || h[stack.peek()] <= h[i]) {
          10                 stack.push(i++);
          11             } else {
          12                 int t = stack.pop();
          13                 maxArea = Math.max(maxArea, h[t] * (stack.isEmpty() ? i : i - stack.peek() - 1));
          14             }
          15         }
          16         return maxArea;
          17     }
          18 }
          posted @ 2014-01-05 12:31 Meng Lee 閱讀(273) | 評(píng)論 (0)編輯 收藏

          主站蜘蛛池模板: 汝城县| 汕尾市| 宝鸡市| 改则县| 鹤庆县| 开远市| 邹城市| 滕州市| 天峨县| 佳木斯市| 台北市| 建宁县| 宜良县| 邯郸市| 屏山县| 松溪县| 吉安市| 卢湾区| 大同县| 高平市| 临朐县| 怀仁县| 毕节市| 若尔盖县| 思茅市| 临桂县| 彭山县| 德州市| 伊春市| 曲周县| 罗田县| 永春县| 施秉县| 房产| 晴隆县| 浪卡子县| 大丰市| 北海市| 灵石县| 固安县| 池州市|