劍指Offer面試題38(Java版):數字在排序數組中出現的次數__劍指offer(Java版)

來源:互聯網
上載者:User

題目:統計一個數字在排序數組中出現的次數。例如輸入排序數組為

{1,2,3,3,,3,3,4,5}和數字3,由於3在這個數組中出現了4次,因此輸出4

既然輸入的數組是排序的,那麼我們很自然的想到利用二分尋找演算法。在題目給出的例子中,我們可以先用二分尋找演算法找到第一個3.由於3可能出現多次,因此我們找到的3的左右兩遍可能都是3,於是我們在找到3的左右兩邊順序掃描,分別找出第一個3和最後一個3.因為要尋找的數字在長度為n的數組中可能很出現O(n)次,所以順序掃描的時間複雜度為O(n)。因此這種演算法的效率和直接從頭到尾順序掃描整個數組統計3出現的次數的方法是一樣的。顯然,面試官是不會滿意這種演算法,它會提示我們還有更快的演算法。

接下來我們思考如何更好的利用二分尋找演算法。假設我們統計數字k在排序數組中出現的次數。在前面的演算法的時間主要消耗在如何確定重複出現的第一個k和最後一個k的位置上,有沒有可以利用的二分尋找演算法直接找到第一個k和最後一個k。

我們先分析如何利用二分尋找在數組中找到第一個k,二分尋找演算法總是先拿數組的中間的數字和k做比較。如果中間的數字比k大,那麼k只能出現在數組的前半段,下一輪我們旨在數組的前半段尋找就可以了。如果中間的數字比k小,那麼k只能出現在數組的後半段,下一輪我們只在數組的後半段尋找就可以了。如果中間的數字和k相等呢。我們先判斷這個數字是不是第一個k。如果位於中間數位前面一個數字不是k,此時中間的數字剛好就是第一個k。如果中間的數位前面一個數字也是k,也就是說第一個k肯定在數組的前半段,下一輪我們仍然需要在數組的前半段尋找。

同理我們利用上面的思路找到最後一個k。

找到第一個k和最後一個k後就可以知道k出現的次數了,

實現代碼如下:

/** * 統計一個數字在排序數組中出現的次數。 * 例如輸入排序數組{1,2,3,3,3,3,4,5}和數字3,由於3在這個數組中出現了4次,因此輸出4 */package swordForOffer;/** * @author JInShuangQi * * 2015年8月9日 */public class E38NumberOfK {private int getFirstK(int[] arr,int k,int left,int right){if(left > right)return -1;int middleIndex = (left+right)/2;int middleData = arr[middleIndex];if(middleData == k){if((middleIndex >0 && arr[middleIndex -1]!=k)|| middleIndex == 0)return middleIndex;elseright = middleIndex -1;}else if(middleData > k)right = middleIndex -1;elseleft = middleIndex +1;return getFirstK(arr,k,left,right);}private int getLastK(int[] arr,int k,int left,int right){if(left > right)return -1;int middleIndex = (left + right)/2;int middleData = arr[middleIndex];if(middleData == k){if((middleIndex <arr.length -1 && arr[middleIndex+1]!=k) || middleIndex ==arr.length-1)return middleIndex;elseleft = middleIndex+1;}else if(middleData <k){left = middleIndex +1;}elseright = middleIndex -1;return getLastK(arr,k,left,right);}public int getNumberOfK(int[] arr,int k){int number = 0;if(arr.length >0){int first = getFirstK(arr,k,0,arr.length-1);int last = getLastK(arr,k,0,arr.length -1);if(first >-1 && last >-1)number =last-first+1;}return number;}public static void main(String[] args){int[] arr= {1,2,3,3,3,3,4,5};E38NumberOfK test = new E38NumberOfK();System.out.println(test.getNumberOfK(arr, 3));}}
在上述代碼中,getFirstK和getLastK都是利用二分尋找法在數組中進行尋找一個合乎要求的數字,它們的時間複雜度都是O(logn),因此getNumberOfK的總的時間複雜度也只有O(logn).

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.