成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java考研試題之數據結構解法

開發 后端
本文講述09年Java考研試題之數據結構解法。文中描述了兩種解法,分別基于遞歸以及消除遞歸。

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

Java考研試題

先來定義結點(為了簡便,省略set/get):

  1. public class Node  
  2. {  
  3.  public int data;  
  4.  public Node link;  
  5. }  

對于這個Java考研試題,我能想到的兩種解法,一個基于遞歸:

遞歸版的思路就是,基于當前結點,如果后一個是倒數第K-1,那么當前結點是所求,若不然,返回當前是倒數第幾個。

  1. public int printRKWithRecur(Node head,int k)  
  2.     {  
  3.         if(k==0||head==null||head.link==null)return 0;  
  4.         if(_recurFind(head.link,k)>=k)return 1;  
  5.         return 0;  
  6.     }  
  7.     private final int _recurFind(Node node, int k) {  
  8.         if(node.link==null)  
  9.         {  
  10.             return 1;  
  11.         }  
  12.         int sRet=_recurFind(node.link,k);  
  13.         if(sRet==k-1)  
  14.         {  
  15.             System.out.println("Got:"+node.data);  
  16.             return k;  
  17.         }  
  18.         return sRet+1;  
  19.     } 

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

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

  1. public static class CycleIntQueue  
  2.     {  
  3.         int[] datas;  
  4.         int top=0;  
  5.         int num=0;  
  6.         public CycleIntQueue(int n)  
  7.         {  
  8.             datas=new int[n];  
  9.         }  
  10.           
  11.         public void push(int i)  
  12.         {  
  13.             datas[(top++)%datas.length]=i;  
  14.             num++;  
  15.               
  16.         }  
  17.         public int numPushed()  
  18.         {  
  19.             return num;  
  20.         }  
  21.           
  22.           
  23.         public int getButtom()  
  24.         {  
  25.             return datas[top%datas.length];  
  26.         }  
  27.     }  
  28.     public int printRKWithCycleQueue(Node head,int k)  
  29.     {  
  30.         if(k==0||head==null)return 0;  
  31.         CycleIntQueue queue=new CycleIntQueue(k);  
  32.         Node cur=head.link;  
  33.         while(cur!=null)  
  34.         {  
  35.             queue.push(cur.data);  
  36.             cur=cur.link;  
  37.         }  
  38.         if(queue.numPushed()return 0;  
  39.           
  40.         System.out.println("Got:"+queue.getButtom());  
  41.         return 1;  
  42.     } 

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

對于此Java考研試題還有另外一種算法,該算法的空間復雜度為O(1),時間復雜度為O(n)。這在空間復雜度和時間復雜度上應該是比較優化了。

本算法的基本思想如下:既然是查找倒數第K個結點(注意,不是正數,否則就沒什么可討論的了),而且鏈表是單向的,還不能改變表結構,這就意味著只能從前往后掃描結點。我們首先要知道這個鏈表有多少個結點(如果總結點數都不知道,何談倒數?),這個非常簡單,只要從頭掃描一下鏈表,再計一下數即可。

在同一時間從事多項工作會大大提升效率,當然,掃描鏈表也不例外,在掃描鏈表的同時,還需要做一些其他的工作。既然只能從前向后掃描鏈表,而且要求倒數第K個結點,那就讓我們把這個鏈表按長度為K分成若干塊,而最后掃描的結果要么結點數是K的整數倍(模為0),要么余數(模)不為0(多出幾個結點,多出的結點數小于K)。

先看看第二種情況。

假設有12個結點的鏈表,每一個結點的值從前往后分別是1至12,如下所示:

1  2  3  4  5  6  7  8  9  10  11 12

假設我們要求倒數第5個結點,我們直接就可以看出結果是8.那么用程序如何處理呢?

先按長度為5將上面的結點分成三個區域,如下:

1 2 3 4 5   6 7 8 9 10   11 12

注意,不是物理分,而是使用變量來保存區域的邊界(也就是區域最后一個結點的對象)。

從上面的分隔可以看出,最后剩下兩個結點,既然是求倒數第5個,而最后剩下了兩個,那么還缺5-2=3個,因此,只需要從倒數第二個塊(6 7 8 9 10)略過前兩個,第三個結點(8)就是我們要求的結果,而5就是題中的k,2就是結點數與k的模,因此,可以推出一個公式,倒數第k個結點就是按長度為k按分成的若干塊中的第二塊的第(結點數 % k+ 1)個結點。

下面來看看(結點數 % k)為0的情況。假設上面的例子中的k為4,正確的輸出結果應為9,分塊如下:

1 2 3 4  5 6 7 8  9 10 11 12

從上面的三個塊可以看出,結果正好是最后一個塊的第一個結點,這時mod為0(mod=結點數 % k),因此,在這種情況也可以使用上面的公式,只是變成了最后一個塊。

根據上面的基本思想可以設兩個指針,p1和p2,其中p1最終指向倒數第2個完整塊,p2最終指向倒數第1個完整塊,對于第一種情況,p1指向5,p2指向10,這時可以使p1向后移動(k - mod)個結點即可(從5移動3個正好是8)。而對于第二種情況,p1指向8,p2指向12,而mod=0,這時的結果仍然是mod+1,也就是p1向后移動1個結點就是所求的結果。 為了滿足(k=結點數)的情況,需要將p1的初始值設為頭結點,這樣如果(k=結點數),就直接從頭結點向后移動一個結點就是最后的結果,如上面的例子求倒數第12個結點,也就是求正數第1個結點。

下面是這個算法的具體實現(包括核心算法、生成鏈表及調用核心算法的代碼):

  1. public class Test  
  2. {  
  3.     static class Node  
  4.     {  
  5.         public int data;  
  6.         public Node nextNode;  
  7.     }  
  8.     //////////////////////////////////////////  
  9.     //  核心算法  
  10.     private static int findNode(Node headNode, int k)  
  11.     {  
  12.         Node p = headNode, p1 = headNode, p2 = null;   
  13.         int count = 0;  //  表示結點數  
  14.         while (p.nextNode != null)  
  15.         {  
  16.             p = p.nextNode;  
  17.             count++;  
  18.             //  遇到k的整數位個結點,進行分塊  
  19.             if (count % k == 0)   
  20.             {                  
  21.                 if (p2 != null)  
  22.                     p1 = p2;  
  23.                 p2 = p;  
  24.             }  
  25.         }  
  26.         //  k超過鏈表結點數,未找到,返回0  
  27.         // 此處也可以用k > count來判斷  
  28.         if (p2 == null)    
  29.         {  
  30.             return 0;  
  31.         }  
  32.         else 
  33.         {  
  34.             int mod = count % k;  
  35.             int offset = mod + 1;  // 任何情況下,最終結果都是p1指向的結點向后移動(mod + 1)個結點  
  36.             for (int i = 0; i < offset; i++)  
  37.                 p1 = p1.nextNode;  
  38.             System.out.println(p1.data);  
  39.             return 1;  
  40.         }  
  41.     }  
  42.     ////////////////////////////////////////  
  43.     public static void main(String[] args) throws Exception  
  44.     {  
  45.         //產生一個包含1個頭結點和120個結點的鏈表  
  46.         Node headNode = new Node();  
  47.         Node p = headNode;  
  48.         for (int i = 0; i < 120; i++)  
  49.         {  
  50.             p.nextNode = new Node();  
  51.             p.nextNode.data = i + 1;  
  52.             p = p.nextNode;  
  53.         }  
  54.         p.nextNode = null;  
  55.         //  開始查找倒數第k個結點,如果找到,返回1,并輸出結點的data值  
  56.         System.out.println(findNode(headNode, 12));  
  57.     }  

上面程序的輸出結果如下:

109
1

【編輯推薦】

  1. Java筆試題:Java基礎概念(附答案)
  2. Java中消除實現繼承和面向接口編程
  3. Red Hat CEO呼吁甲骨文繼續保持Java開放
  4. 自學Javabean迅速成為Java高手
  5. Java通過JNI調用C語言的方法
責任編輯:王觀 來源: 中國IT實驗室
相關推薦

2021-07-16 07:57:34

Python數據結構

2022-09-26 07:56:53

AVL算法二叉樹

2022-09-21 07:57:33

二叉搜索樹排序二叉樹

2021-07-13 07:52:03

Python數據結構

2021-07-15 06:43:12

Python數據結構

2023-03-28 07:44:23

數據結構數組

2017-03-01 13:58:46

Python數據結構鏈表

2021-07-11 12:06:43

python數據結構

2012-02-02 10:21:05

單鏈表nexthead

2018-06-06 08:54:23

數據結構存儲

2024-10-11 16:43:05

高并發數據結構技巧

2011-03-31 15:41:51

Cacti數據表結構

2020-12-31 05:31:01

數據結構算法

2021-05-10 07:08:41

數據結構緩存

2023-10-31 08:51:25

數據結構存儲數據

2022-01-18 19:13:52

背包問題數據結構算法

2020-10-30 09:56:59

Trie樹之美

2021-08-29 07:41:48

數據HashMap底層

2009-08-12 18:35:17

C#數據結構

2012-04-28 14:21:47

Java數據結構線性結構
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产乱码精品一区二区三区中文 | 日韩在线免费观看视频 | 精品国产乱码久久久久久丨区2区 | 日本三级电影在线看 | 五月天婷婷狠狠 | 欧美一区二区三区在线播放 | 一二三区视频 | 天天草视频 | 婷婷在线网站 | www.99热.com | 国产一区二区在线视频 | 亚洲视频免费一区 | 亚洲精品国产a久久久久久 中文字幕一区二区三区四区五区 | 欧美中文一区 | 亚洲一区二区三区在线视频 | 九九九色 | 天天干天天爽 | 欧美国产中文字幕 | 国产激情一区二区三区 | 亚洲欧美一区二区三区在线 | 欧美a级成人淫片免费看 | 亚洲精品一区国产精品 | 中文字幕一区在线观看视频 | 少妇一级淫片免费放播放 | 涩涩视频在线观看免费 | 91中文字幕在线观看 | 久草免费在线 | 国产夜恋视频在线观看 | 国产精品亚洲成在人线 | 四虎成人免费视频 | 久热久 | 国产91久久久久久久免费 | 国产精品久久国产精品99 | 日韩在线中文 | 国产精品毛片 | 久久国产精品精品国产色婷婷 | 日韩视频在线免费观看 | 亚洲精品免费在线 | 精品国产乱码久久久久久蜜退臀 | 亚洲成人综合社区 | 涩在线 |