隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
          數據加載中……

          Twitter算法面試題詳解(Java實現)

          最近在網上看到一道Twitter的算法面試題,網上已經有人給出了答案,不過可能有些人沒太看明白(我也未驗證是否正確),現在給出一個比較好理解的答案。先看一下題目。

          圖1

               先看看圖圖1。可以將方塊看做磚。題干很簡單,問最多能放多少水。例如,圖2就是圖1可放的最多水(藍色部分),如果將一塊磚看做1的話,圖2就是能放10個單位的水。

          圖2

          再看個例子

          圖3

          圖3可以放17個單位的水。

          上面每一個圖的磚墻用int數組表示,每一個數組元素表示每一列磚墻的磚數(高度),例如,圖3用數組表示就是int[] wallHeights = new int[]{2, 5, 1, 3, 1, 2, 1, 7, 7, 6};

          這里某人給出了python的算法點擊打開鏈接,不過有人說有問題,有python環境的可以驗證。現在給出我的Java算法。

          算法原理

                其實很簡單,我的算法并不是累加的,而是用的減法,先用圖3為例。只需要找到所有墻中最高的,然后再找出第二高的。如果兩堵墻緊鄰者,就忽略它,否則算一 下 如果墻之間沒有任何其他的磚的情況下可以有多少水(只是一個乘法而已),然后掃描兩堵墻之間有多少塊磚,減去這個磚數就可以了。最后用遞歸處理。將兩堵墻 兩側到各自的左右邊界再重新進行前面的操作(遞歸處理)。直到無墻可處理。 用遞歸方法很容易理解。下面看一下算法的詳細代碼。

          復制代碼
          public class Test  
          {  
              static int result = 0;  //  最終結果  
              static int[] wallHeights = new int[]  
              {1,6,1,2,3,4,100,1,9};  //  表示所有的墻的高度  
            
              public static void process(int start, int end)  
              {  
                  //  first:start和end之間最高的墻  
                  //  second:start和end之間第二高的墻  
                  int first = 0, second = 0;  
                  //  firstIndex:第一高的墻在wallHeights中的索引  
                  //  secondIndex:第二高的墻在wallHeights中的索引  
                  int firstIndex = 0, secondIndex = 0;  
                  //  兩堵墻必須至少有一堵墻的距離  
                  if (end - start <= 1)  
                      return;  
                  //  開始獲取第一高和第二高墻的磚數  
                  for (int i = start; i <= end; i++)  
                  {  
                      if (wallHeights[i] > first)  
                      {  
                          second = first;  
                          secondIndex = firstIndex;  
                          first = wallHeights[i];  
                          firstIndex = i;  
                      }  
                      else if (wallHeights[i] > second)  
                      {  
                          second = wallHeights[i];  
                          secondIndex = i;  
                      }  
                  }  
            
                  //  獲取左側墻的索引  
                  int startIndex = Math.min(firstIndex, secondIndex);  
                  //  獲取右側墻的索引  
                  int endIndex = Math.max(firstIndex, secondIndex);  
                  //  計算距離  
                  int distance = endIndex - startIndex;  
                  //  如果第一高的墻和第二高的墻之間至少有一堵墻,那么開始計算這兩堵墻之間可以放多少個單位的水  
                  if (distance > 1)  
                  {  
                      result = result + (distance - 1) * second;  
                      //  減去這兩堵墻之間的磚數  
                      for (int i = startIndex + 1; i < endIndex; i++)  
                      {  
                          result -= wallHeights[i];  
                      }  
                        
                  }  
                  //  開始遞歸處理左側墻距離開始位置能放多少水  
                  process(start, startIndex);  
                  //  開始遞歸處理右側墻距離結束位置能放多少水  
                  process(endIndex, end);  
              }  
              public static void main(String[] args)  
              {  
                  process(0, wallHeights.length - 1);  
                  System.out.println(result); 
              }  
          }  
          復制代碼

          代碼中的測試用例的結果是22。下面是幾組測試用例。

           

          [2,5,1,2,3,4,7,7,6]   結果:10
          [2,5,1,3,1,2,1,7,7,6]  結果:17
          [6,1,4,6,7,5,1,6,4]   結果:13
          [9,6,1,2,3,4,50,1,9]  結果:37


          有其他算法的(語言不限)歡迎跟帖

           





          Android開發完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2013-11-03 18:03 銀河使者 閱讀(8617) 評論(4)  編輯  收藏 所屬分類: algorithm 原創

          評論

          # re: Twitter算法面試題詳解(Java實現)  回復  更多評論   

          囧,遞歸lol~ 貼一個自己在leetcode上的實現。因為是直接在oj上寫的,不考慮額外空間問題,當然了這段代碼可以重構^_^.

          http://oj.leetcode.com/problems/trapping-rain-water/

          class Solution {
          public:
          int trap(int A[], int n) {
          // Note: The Solution object is instantiated only once and is reused by each test case.

          // easiest and intuitive way:
          // caculate the (left_max, right_max) for each element A[i]
          // example:
          // for the given array A = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1], the points whould be:
          // B = [(0, 3), (1, 3), (1, 3), (2, 3), (2, 3), (2, 3), (2, 3), (3, 2), (3, 2), (3, 2), (3, 1)]
          // then let SUM = sum( min(Bi) ) for i = 0 to n-1
          // return SUM - sum(Ai) for i = 0 to n-1
          // and hope this works!
          // luckily, it works!

          vector<int> left(n, 0), right(n, 0);
          int max = 0;
          for(int i=0; i<n; i++)
          {
          if(A[i] > max)
          max = A[i];

          left[i] = max; // don't use push_back
          }

          // for right
          max = 0;
          for(int i=n-1; i>=0; i--)
          {
          if(A[i] > max)
          max = A[i];

          right[i] = max;
          }

          int sum=0;
          for(int i=0; i<n; i++)
          {
          int min = (left[i] < right[i]) ? left[i] : right[i];
          sum += (min-A[i]); // don't forget to subtract A[i]
          }

          return sum;
          }
          };
          2013-11-19 01:57 | zyzz

          # re: Twitter算法面試題詳解(Java實現)  回復  更多評論   

          好東西 學習了
          2013-12-05 10:23 | 左岸

          # re: Twitter算法面試題詳解(Java實現)[未登錄]  回復  更多評論   

          package yang.twitter;

          /**
          * @author dy35978
          *
          */
          public class TwitterProcess {
          private static int [] wallHeights = {1,6,1,2,3,4,100,1,9};
          private static int result = 0;//最多裝水
          private static void process(int start, int end){
          int firstWall = 0;//最高墻
          int secondWall = 0;//次高墻
          int firstIndex = 0;//最高墻下標
          int secondIndex = 0;//次高墻下標
          int maxIndex = 0;//較大下標
          int minIndex = 0;//較小下標
          //end-start<=1 不只是等于1,注意
          if(end-start<=1){
          return;
          }
          for(int i=0;i<end+1;i++){
          if(wallHeights[i]>=firstWall){
          secondWall = firstWall;
          secondIndex = firstIndex;
          firstWall = wallHeights[i];
          firstIndex = i;
          }else{
          if(wallHeights[i]>=secondWall){
          secondIndex = i;
          secondWall = wallHeights[i];
          }
          }
          }
          maxIndex = secondIndex>firstIndex?secondIndex:firstIndex;// Math.min(firstIndex, secondIndex);
          minIndex = secondIndex<firstIndex?secondIndex:firstIndex;// Math.max(firstIndex, secondIndex);
          if(maxIndex-minIndex>1){
          result =result+ secondWall*(maxIndex-minIndex-1);
          for(int i=minIndex+1;i<maxIndex;i++){
          result = result-wallHeights[i];
          }
          }
          // 開始遞歸處理左側墻距離開始位置能放多少水
          process(start,minIndex);
          // 開始遞歸處理右側墻距離結束位置能放多少水
          process(maxIndex,end);
          }

          /**
          * @param args
          */
          public static void main(String[] args) {
          // TODO Auto-generated method stub

          process(0,wallHeights.length-1);
          System.out.println("wallHeights結果:"+result);
          }

          }
          2013-12-17 11:32 | Blues

          # re: Twitter算法面試題詳解(Java實現)  回復  更多評論   

          很難啊.
          2014-07-24 13:21 | 微觀互聯網
          主站蜘蛛池模板: 英山县| 宁陵县| 西峡县| 雅安市| 湛江市| 利辛县| 麟游县| 瑞金市| 墨脱县| 延庆县| 衡南县| 康马县| 太谷县| 新巴尔虎右旗| 根河市| 东至县| 东辽县| 周宁县| 余姚市| 开封县| 额尔古纳市| 万宁市| 松溪县| 嘉兴市| 陇川县| 驻马店市| 寿宁县| 手游| 云阳县| 永和县| 黄大仙区| 六盘水市| 望奎县| 伽师县| 营口市| 江陵县| 普兰县| 兴隆县| 南陵县| 麻城市| 大埔县|