E81086713E446D36F62B2AA2A3502B5EB155

          Java雜家

          雜七雜八。。。一家之言

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks




          今天去網上看了一下09年的考研試題,看見該題目(圖片):



          先來定義結點(為了簡便,省略set/get):
          public class Node
          {
           
          public int data;
           
          public Node link;
          }
          我能想到的兩種解法,一個基于遞歸:

          遞歸版的思路就是,基于當前結點,如果后一個是倒數第K-1,那么當前結點是所求,若不然,返回當前是倒數第幾個。
          public int printRKWithRecur(Node head,int k)
              {
                  
          if(k==0||head==null||head.link==null)return 0;
                  
          if(_recurFind(head.link,k)>=k)return 1;
                  
          return 0;
              }
              
          private final int _recurFind(Node node, int k) {
                  
          if(node.link==null)
                  {
                      
          return 1;
                  }
                  
          int sRet=_recurFind(node.link,k);
                  
          if(sRet==k-1)
                  {
                      System.out.println(
          "Got:"+node.data);
                      
          return k;
                  }
                  
          return sRet+1;
              }


          對每個結點,該算法都只訪問一次,因此復雜度O(N).

          第二解法,相對遞歸來說,這種方法可以算是消除遞歸版,而且從某種意義上來說比遞歸更高效,跟省空間,遞歸版實際上是把回溯的數據存在棧上,而版方法是自己存儲,且利用數組實現一個循環隊列,只存儲K個元素。

          public static class CycleIntQueue
              {
                  
          int[] datas;
                  
          int top=0;
                  
          int num=0;
                  
          public CycleIntQueue(int n)
                  {
                      datas
          =new int[n];
                  }
                  
                  
          public void push(int i)
                  {
                      datas[(top
          ++)%datas.length]=i;
                      num
          ++;
                      
                  }
                  
          public int numPushed()
                  {
                      
          return num;
                  }
                  
                  
                  
          public int getButtom()
                  {
                      
          return datas[top%datas.length];
                  }
              }
              
          public int printRKWithCycleQueue(Node head,int k)
              {
                  
          if(k==0||head==null)return 0;
                  CycleIntQueue queue
          =new CycleIntQueue(k);
                  Node cur
          =head.link;
                  
          while(cur!=null)
                  {
                      queue.push(cur.data);
                      cur
          =cur.link;
                  }
                  
          if(queue.numPushed()<k)return 0;
                  
                  System.out.println(
          "Got:"+queue.getButtom());
                  
          return 1;
              }

          本算法,都每個結點也只放一次,另外進行一次入隊操作,該操作復雜度O(1),從而,整個算法復雜度仍是O(N).


          posted on 2009-01-17 13:56 DoubleH 閱讀(2290) 評論(5)  編輯  收藏

          Feedback

          # re: [算法]09考研數據結構試題解法 2009-01-17 15:41 crtylr
          個人覺得根本就用不著那么,麻煩的方法
          兩個指針,第一個指向頭,另一個指向從頭開始的指向第K個
          然后兩個指針分別指向Next,
          直到第二個指針指向了Null,那第一個指針的元素就是所求的倒數第K個  回復  更多評論
            

          # re: [算法]09考研數據結構試題解法 2009-01-17 20:53 銀河使者
          這是一個算法,詳細解釋見我的blog:
          http://www.aygfsteel.com/nokiaguy/archive/2009/01/17/251722.html

              private static int findNode(Node headNode, int k)
              {
                  Node p = headNode, p1 = headNode, p2 = null;
                  int count = 0;  //  表示結點數
                  while (p.nextNode != null)
                  {
                      p = p.nextNode;
                      count++;
                      //  遇到k的整數位個結點,進行分塊
                      if (count % k == 0)
                      {                
                          if (p2 != null)
                              p1 = p2;
                          p2 = p;
                      }
                  }
                  //  k超過鏈表結點數,未找到,返回0
                  if (p2 == null)
                  {
                      return 0;
                  }
                  else
                  {
                      int mod = count % k;
                      int offset = mod + 1;  // 任何情況下,最終結果都是p1指向的結點向后移動(mod + 1)個結點
                      for (int i = 0; i < offset; i++)
                          p1 = p1.nextNode;
                      System.out.println(p1.data);
                      return 1;
                  }
              }

            回復  更多評論
            

          # re: [算法]09考研數據結構試題解法 2009-01-17 22:48 DoubleH
          @crtylr
          @銀河使者
          恩,二位的想法其實是一樣的,銀河使者其實就是crtylr的復雜版。crtylr的意思應該是對頭K個元素,只移動一個指針,然后一起移動直到第一個指針沒法繼續。  回復  更多評論
            

          # re: [算法]09考研數據結構試題解法 2009-01-18 10:39 銀河使者
          是的,@crtylr的算法比較好,下面的具體的實現代碼,很簡單:
              private static int findNode(Node headNode, int k)
              {       
                  Node p1 = headNode, p2 = headNode;
                  for(int i = 0; i < k && p2.nextNode != null; i++)
                      p2 = p2.nextNode;
                  if(p2.nextNode == null) return 0;
                  while(p2.nextNode != null)
                  {
                      p1 = p1.nextNode;
                      p2 = p2.nextNode;
                  }
                  System.out.println(p1.nextNode.data);
                  return 1;
              }   回復  更多評論
            

          # re: [算法]09考研數據結構試題解法[未登錄] 2009-01-20 19:14 hehe
          這道題目好熟悉阿.. 呵呵
            回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 沂源县| 永和县| 化州市| 大城县| 兴化市| 延庆县| 高密市| 东城区| 平顺县| 衡阳市| 凤山县| 大方县| 亚东县| 景谷| 繁峙县| 维西| 石棉县| 利川市| 莆田市| 兴城市| 和政县| 茂名市| 涞水县| 伽师县| 内乡县| 竹北市| 遵义县| 溧阳市| 体育| 界首市| 冕宁县| 金溪县| 鹤山市| 长子县| 潮安县| 育儿| 大港区| 原平市| 喀喇沁旗| 广水市| 靖西县|