1. 程式人生 > >程式設計師面試100題之十一 陣列迴圈移位

程式設計師面試100題之十一 陣列迴圈移位

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

                      設計一個演算法,把一個含有N個元素的陣列迴圈右移K位,要求時間複雜度為O(N),且只允許使用兩個附加變數。

     不合題意的解法如下:

     我們先試驗簡單的辦法,可以每次將陣列中的元素右移一位,迴圈K次。abcd1234--->4abcd123--->34abcd12--->234abcd1--->1234abcd。程式碼如下所示:

RightShift(int *arr, int N, int K){ while(K--) {  int t = arr[N - 1];  for(int i = N - 1 ; i > 0 ; i--)  {   arr[i] = arr[i - 1
];  }  arr[0] = t; }}

       雖然這個演算法可以實現陣列的迴圈右移,但是演算法複雜度為O(K*N),不符合題目的要求,要繼續探索。

       分析與解法

      假如陣列為abcd1234,迴圈右移4位的話,我們希望達到的狀態是1234abcd。不妨設K是一個非負的整數,當K為負整數的時候,右移K位,相當於左移(-K)位,左移和右移在本質上是一樣的。

      解法一

   大家開始可能會有這樣的潛在假設,K<N。事實上,很多時候也的確是這樣的。但嚴格來說,我們不能用這樣的“慣性思維”來思考問題。尤其在程式設計的時候,全面地考慮問題是很重要的,K可能是一個遠大於N的整數,在這個時候,上面的解法是需要改進的。

仔細觀察迴圈右移的特點,不難發現:每個元素右移N位後都會回到自己的位置上。因此,如果K>N,右移K-N以後的陣列序列跟右移K位的結果是一樣的。進而可得出一條通用的規律:右移K位之後的情形,跟右移K’=K%N位之後的情形一樣,程式碼如下所示:

RightShift(int *arr, int N, int K){ K = K % N ; while(K--) {  int t = arr[N - 1];  for(int i = N - 1 ; i > 0 ; i--)  {   arr[i] = arr[i - 1];  }  arr[0] = t; }}

     可見,增加考慮迴圈右移的特點之後,演算法複雜度降為O(N^2),這跟K無關,與題目的要求又接近了一步。但時間複雜度還不夠低,接下來讓我們繼續挖掘迴圈右移前後,陣列之間的關聯。

    解法二

      我們還是把字串看成有兩段組成的,記位XY。左旋轉相當於要把字串XY變成YX。我們先在字串上定義一種翻轉的操作,就是翻轉字串中字元的先後順序。把X翻轉後記為XT。顯然有(XT)T=X。

      我們首先對X和Y兩段分別進行翻轉操作,這樣就能得到XTYT。接著再對XTYT進行翻轉操作,得到(XTYT)T=(YT)T(XT)T=YX。正好是我們期待的結果。

      分析到這裡我們再回到原來的題目。我們要做的僅僅是把字串分成兩段,第一段為前面m個字元,其餘的字元分到第二段。再定義一個翻轉字串的函式,按照前面的步驟翻轉三次就行了。時間複雜度和空間複雜度都合乎要求。

假設原陣列序列為abcd1234,要求變換成的陣列序列為1234abcd,即迴圈右移了4位。比較之後,不難看出,其中有兩段的順序是不變的:1234和abcd,可把這兩段看成兩個整體,右移K位的過程就是把陣列的兩部分交換一下,變換的過程通過一下步驟完成:

1、逆序排列abcd:abcd1234--->dcba1234;

2、逆序排列1234:dcba1234--->dcba4321;

3、全部逆序:dcba4321--->1234abcd。

程式碼如下所示:

Reverse(int *arr, int b, int e)      //逆序排列for( ; b < e; b++, e--)    //從陣列的前、後一起遍歷 {  int temp = arr[e];  arr[e] = arr[b];  arr[b] = temp; }}RightShift(int *arr, int N, int K){ K = K % N ; Reverse(arr, 0, N-K-1);     //前面N-K部分逆序 Reverse(arr, N-K, N-1);     //後面K部分逆序 Reverse(arr, 0, N-1);       //全部逆序}

這樣,我們就可以線上性時間內實現右移操作了。


           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述