<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    IT技術小屋

    秋風秋雨,皆入我心

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      38 隨筆 :: 1 文章 :: 19 評論 :: 0 Trackbacks

    置頂隨筆 #

    Memcached是被廣泛使用的分布式緩存技術。不同的語言有不同的Memcached客戶端程序,對于Java客戶端來說,首推Memcached Java Client(http://github.com/gwhalin/Memcached-Java-Client )。

    這次,Memcached Java Client推出的2.6.1發布版是基于全新的performance分支,具有如下重大改進:

    1. 較之老版本,在性能上有300%左右的提升;
    2. 兼容老版本,用戶無須修改自己的源代碼;
    3. 支持多個memcached協議,包括text,udp和binary協議;
    4. 支持SASL認證機制;
    5. 重新實現的連接池,修復了之前的連接數太多所導致的OutOfMemory異常;
    6. 加入了slf4j logger支持,使得開發人員可以方便的記錄日志;
    7. 支持自定義的對象序列化方法。

    這個分支由Schooner Information Technology貢獻,并由Schooner中國團隊完成開發,可以通過以下郵箱聯系作者:jowett.lee@gmail.com

    可以從這里下載二進制包:https://github.com/gwhalin/Memcached-Java-Client/downloads 
    源代碼在github上,http://github.com/gwhalin/Memcached-Java-Client ,然后選擇performance分支。

    下面是一些性能測試的數據,包括了當前流行的Memcached Java Client。其中,schooner指的是這個分支的text protocol, schooner_bin指的是binary protocol,鏈接是:https://github.com/gwhalin/Memcached-Java-Client/wiki/PERFORMANC

    轉載請注明出處:http://www.tkk7.com/menglee/archive/2011/06/29/353375.html


    posted @ 2011-06-29 18:09 Meng Lee 閱讀(2454) | 評論 (2)編輯 收藏

    2016年11月13日 #

    本文介紹了包括 Python、Java、Haskell等在內的一系列編程語言的深度學習庫。

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

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

    2014年6月13日 #

    今天,終于有時間靜下心來回顧過去兩年來所做的事情,感慨萬千,一時之間竟不知從何說起。兩年以來,遇到的困難著實不少,但每每遭遇挫折與不順之后,卻往往能柳暗花明,遇到新的轉機,讓我真真切切地感受到了功夫不負有心人這句話的含意。

    一、為什么要出國
    其實,之前從來沒有考慮過要出國,更沒有想過能直接出國工作。回想一下,這個決定的做出,多半還是緣于自己骨子里的不安分。我從很大程度上來說是一個閑不住的人,從小學、中學、大學到研究生,我幾乎每天都有明確的目標。然而,2013年從公司到事業單位工作以后,我的生活發生了巨大地轉變。簡單的工作、空洞的公文、無聊的活動占據了我全部的工作任務。有段時間幾乎天天寫材料搞活動。領導經常夸我材料寫得又快又好,活動也搞得有聲有色,心里感覺很有成就感。然而,時間一長,逐漸發現那些公文永遠是一個套路,以至于我分門別類,摸索出了幾個萬能模板。而活動則千篇一律,讓人疲于應付。我甚至可以看到六十歲退休時我在干什么,于是一陣恐懼感常常會莫名襲來,因為我不安分、不滿足于此。我不能放棄所學所長,我不能庸庸碌碌在這里度過未來的幾十年,我還有夢想,我還要登高看世界。為了這個,我走過了不平凡的兩年。

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

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

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

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

    回顧兩年來的努力,終于要實現自己的夢想了,感慨萬千。在短短的人生中,能有這一段不尋常的經歷,我覺得十分幸運。展望未來,我想讀萬卷書不如行萬里路,未來希望能夠利用在倫敦工作的機會,盡量多去歐洲各國走走,豐富自己的閱歷,開拓自己的眼界。

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

    2014年1月14日 #

    算法很簡單,核心思想是:對某個值A[i]來說,能trapped的最多的water取決于在i之前最高的值leftMostHeight[i]和在i右邊的最高的值rightMostHeight[i]。(均不包含自身)。如果min(left,right) > A[i],那么在i這個位置上能trapped的water就是min(left,right) – A[i]。
    有了這個想法就好辦了,第一遍從左到右計算數組leftMostHeight,第二遍從右到左計算rightMostHeight,在第二遍的同時就可以計算出i位置的結果了,而且并不需要開空間來存放rightMostHeight數組。
    時間復雜度是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 閱讀(221) | 評論 (0)編輯 收藏

    2014年1月7日 #

    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.

    這道題其實有很強的規律可循。首先,n個元素的排列總數是n!。在下面的分析中,讓k的范圍是0 <= k < n!。(題目代碼實際上是1<=k<=n!)
    可以看到一個規律,就是這n!個排列中,第一位的元素總是(n-1)!一組出現的,也就說如果p = k / (n-1)!,那么排列的最開始一個元素一定是arr[p]。
    這個規律可以類推下去,在剩余的n-1個元素中逐漸挑選出第二個,第三個,...,到第n個元素。程序就結束。
     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 閱讀(450) | 評論 (0)編輯 收藏

    2014年1月6日 #

    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 閱讀(345) | 評論 (0)編輯 收藏

    2014年1月5日 #

    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 閱讀(219) | 評論 (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.

    本題需要使用棧維護一個高度單調遞增的序列下標,如果遇到一個元素比當前棧頂元素高度小,那么出棧,并計算當前最大面積。如果棧為空,需要特殊考慮。
     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 閱讀(272) | 評論 (0)編輯 收藏

    2014年1月4日 #

    Given a binary tree, return the inorder traversal of its nodes' values.
    For example:
    Given binary tree {1,#,2,3},
       1
        \
         2
        /
       3
    return [1,3,2].
    Note: Recursive solution is trivial, could you do it iteratively?

    切記p節點初始時指向root.left。代碼如下:
     1 public class BinaryTreeInorderTraversal {
     2     public ArrayList<Integer> inorderTraversal(TreeNode root) {
     3         ArrayList<Integer> inOrder = new ArrayList<Integer>();
     4         if (root == null)
     5             return inOrder;
     6         Stack<TreeNode> s = new Stack<TreeNode>();
     7         s.add(root);
     8         TreeNode p = root.left;
     9         while (!s.empty()) {
    10             while (p != null) {
    11                 s.add(p);
    12                 p = p.left;
    13             }
    14             TreeNode n = s.pop();
    15             inOrder.add(n.val);
    16             p = n.right;
    17             if (p != null) {
    18                 s.add(p);
    19                 p = p.left;
    20             }
    21         }
    22         return inOrder;
    23     }
    24 }
    posted @ 2014-01-04 11:17 Meng Lee 閱讀(169) | 評論 (0)編輯 收藏

    2014年1月3日 #

    Given a collection of integers that might contain duplicates, S, return all possible subsets.
    Note:
    Elements in a subset must be in non-descending order.
    The solution set must not contain duplicate subsets.
    For example,
    If S = [1,2,2], a solution is:
    [
      [2],
      [1],
      [1,2,2],
      [2,2],
      [1,2],
      []
    ]

    由于元素中可能存在重復,因此較之于Subset的實現,需要加一些判斷。如果碰到了重復元素,只需要在上一次迭代新增的子集的基礎上再進行迭代即可。實現代碼如下:
     1 public class SubsetsII {
     2     public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) {
     3         ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
     4         ArrayList<ArrayList<Integer>> lastLevel = null;
     5         ret.add(new ArrayList<Integer>());
     6         Arrays.sort(num);
     7         for (int i = 0; i < num.length; i++) {
     8             ArrayList<ArrayList<Integer>> tmp = new ArrayList<ArrayList<Integer>>();
     9             ArrayList<ArrayList<Integer>> prev = i == 0 || num[i] != num[i - 1] ? ret : lastLevel;
    10             for (ArrayList<Integer> s : prev) {
    11                 ArrayList<Integer> newSet = new ArrayList<Integer>(s);
    12                 newSet.add(num[i]);
    13                 tmp.add(newSet);
    14             }
    15             ret.addAll(tmp);
    16             lastLevel = tmp;
    17         }
    18         return ret;
    19     }
    20 }
    posted @ 2014-01-03 16:40 Meng Lee 閱讀(182) | 評論 (0)編輯 收藏

    2014年1月2日 #

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:
    Only one letter can be changed at a time
    Each intermediate word must exist in the dictionary
    For example,
    Given:
    start = "hit"
    end = "cog"
    dict = ["hot","dot","dog","lot","log"]
    Return
      [
        ["hit","hot","dot","dog","cog"],
        ["hit","hot","lot","log","cog"]
      ]
    Note:
    All words have the same length.
    All words contain only lowercase alphabetic characters.

    這個題目應該算是leetcode上比較難的題目了。剛開始我采用了和Word Ladder相似的做法,只是用ArrayList記錄了當前變換路徑,在小數據的情況下可以Accept,但是大數據超時。究其原因,是由于為每個當前節點記錄變換路徑的時候,需要復制之前的ArrayList,這個時間開銷較大。
    其實,我們可以采用一個Map<String, HashSet<String>>結構,記錄字典單詞的每一個前驅,這樣我們可以從end反向遍歷,構造出轉換路徑。
    同時,我利用了兩個ArrayList,交替記錄上一層和下一層的節點,如果下一層節點為空,則不存在路徑,立即返回。如果下一層中出現了end,證明找到了所有的最短路徑,停止搜索開始構造路徑。實現代碼如下:
     1 public class WordLadderII {
     2     private void GeneratePath(Map<String, ArrayList<String>> prevMap,
     3             ArrayList<String> path, String word,
     4             ArrayList<ArrayList<String>> ret) {
     5         if (prevMap.get(word).size() == 0) {
     6             path.add(0, word);
     7             ArrayList<String> curPath = new ArrayList<String>(path);
     8             ret.add(curPath);
     9             path.remove(0);
    10             return;
    11         }
    12 
    13         path.add(0, word);
    14         for (String pt : prevMap.get(word)) {
    15             GeneratePath(prevMap, path, pt, ret);
    16         }
    17         path.remove(0);
    18     }
    19 
    20     public ArrayList<ArrayList<String>> findLadders(String start, String end,
    21             HashSet<String> dict) {
    22         ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
    23         Map<String, ArrayList<String>> prevMap = new HashMap<String, ArrayList<String>>();
    24         dict.add(start);
    25         dict.add(end);
    26         for (String d : dict) {
    27             prevMap.put(d, new ArrayList<String>());
    28         }
    29         ArrayList<HashSet<String>> candidates = new ArrayList<HashSet<String>>();
    30         candidates.add(new HashSet<String>());
    31         candidates.add(new HashSet<String>());
    32         int current = 0;
    33         int previous = 1;
    34         candidates.get(current).add(start);
    35         while (true) {
    36             current = current == 0 ? 1 : 0;
    37             previous = previous == 0 ? 1 : 0;
    38             for (String d : candidates.get(previous)) {
    39                 dict.remove(d);
    40             }
    41             candidates.get(current).clear();
    42             for (String wd : candidates.get(previous)) {
    43                 for (int pos = 0; pos < wd.length(); ++pos) {
    44                     StringBuffer word = new StringBuffer(wd);
    45                     for (int i = 'a'; i <= 'z'; ++i) {
    46                         if (wd.charAt(pos) == i) {
    47                             continue;
    48                         }
    49 
    50                         word.setCharAt(pos, (char) i);
    51 
    52                         if (dict.contains(word.toString())) {
    53                             prevMap.get(word.toString()).add(wd);
    54                             candidates.get(current).add(word.toString());
    55                         }
    56                     }
    57                 }
    58             }
    59 
    60             if (candidates.get(current).size() == 0) {
    61                 return ret;
    62             }
    63             if (candidates.get(current).contains(end)) {
    64                 break;
    65             }
    66         }
    67 
    68         ArrayList<String> path = new ArrayList<String>();
    69         GeneratePath(prevMap, path, end, ret);
    70 
    71         return ret;
    72     }
    73 }
    posted @ 2014-01-02 13:59 Meng Lee 閱讀(865) | 評論 (0)編輯 收藏

    僅列出標題  下一頁
    主站蜘蛛池模板: 日本卡1卡2卡三卡免费| 99在线在线视频免费视频观看| www.亚洲精品.com| 成人精品一区二区三区不卡免费看 | 日本免费一区二区久久人人澡| 色婷婷亚洲十月十月色天| 成年女人喷潮毛片免费播放| 老司机午夜性生免费福利 | 免费理论片51人人看电影| 精品乱子伦一区二区三区高清免费播放 | 国产精品亚洲四区在线观看| 亚洲第一黄片大全| 在线看片v免费观看视频777 | 国产免费的野战视频| 免费国产va在线观看| 亚洲毛片免费视频| 亚洲精品第一国产综合精品99| 16女性下面扒开无遮挡免费| 国产成人精品亚洲| 亚洲精品亚洲人成在线观看麻豆| 亚洲成aⅴ人片久青草影院| 在线观看永久免费| 久久成人永久免费播放| 亚洲乱码日产精品一二三| 亚洲国产成人精品不卡青青草原| 国产成人免费福利网站| 国产92成人精品视频免费| 国产真人无码作爱免费视频| 亚洲AV无码专区在线电影成人| 亚洲AV无码国产精品麻豆天美 | 亚洲黄黄黄网站在线观看| 黄色片在线免费观看| 免费观看久久精彩视频| 老司机午夜性生免费福利| 99999久久久久久亚洲| 久久亚洲精品国产精品| 黑人大战亚洲人精品一区| 全部免费a级毛片| 成人免费无码大片a毛片| 日本免费xxxx色视频| 国产婷婷成人久久Av免费高清|