1008 陣列元素迴圈右移問題 C及C 實現

2021-09-01 11:50:05 字數 3602 閱讀 8005

1008 陣列元素迴圈右移問題 (20 point(s))

乙個陣列a中存有n(>0)個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向右移m(≥0)個位置,即將a中的資料由(a​0​​a​1​​⋯a​n−1​​)變換為(a​n−m​​⋯a​n−1​​a​0​​a​1​​⋯a​n−m−1​​)(最後m個數迴圈移至最前面的m個位置)。如果需要考慮程式移動資料的次數盡量少,要如何設計移動的方法?

每個輸入包含乙個測試用例,第1行輸入n(1≤n≤100)和m(≥0);第2行輸入n個整數,之間用空格分隔。

在一行中輸出迴圈右移m位以後的整數序列,之間用空格分隔,序列結尾不能有多餘空格。

6 2

1 2 3 4 5 6

5 6 1 2 3 4
這道題屬於模擬運動與計算的題目,是一類常見的題。比如模擬圓餅移動、乘除法、鍊錶等等。解決這類問題的關鍵在於熟練掌握常見運動與計算的過程,並具有較熟練的程式設計能力。

標準:陣列元素迴圈右移只需要每次移動一位數字,然後移動幾位就有幾個迴圈即可。每乙個移動過程中,將最後一位數字取出來放在tmp中,然後左邊的數字都往右移動一位,最後再把tmp的數字放回到左邊下標為0的位置。見**1、2~

其他思路:這道題也可以採用這樣一種思路

實際上就是把需要移動的全部存到乙個新的陣列中。然後再重新填回去a就行。見**3。這裡要注意m=0時,無法開闢長度為0 的陣列,因此要單獨將m>0拿出來。

填回去之後提交並不能完全ac,這裡要注意題目只說了m>=0,沒說m會小於n,因此不能ac的兩個測試樣例可能是m>n了,因此要將**3改一改。也比較容易,因為如果陣列完全移動n個位置的話會變回原陣列,也就是說週期為n,因此只要將m%n,取餘數就可以是最後的移動效果。見**4。

採用這種方式,可以在m很大的時候,減小移動的時間複雜度,相比於**2這種移動效率也會比較高。

那麼問題來了,能不能將標準演算法的**2的移動效率在m>n時提高呢?顯然也是可以的,只需要將第二個for迴圈裡的i

修改之後的**見**5。**最後的注釋部分可以看出優化後的效果,時間上縮小了70倍左右。

對於**4,實際上可以偷懶,將前後兩部分取出來之後,可以不用再放回a陣列,直接輸出就行。由於ac時只看輸出結果,因此並不影響,而且時間複雜度可以減少一半。見**6.

網上見到了乙個使用庫函式的好方法。既然有對應的函式,就省了很多事啦~。見**7.

reverse()函式包含在標頭檔案中。該標頭檔案還有常用的sort()函式。

c++ < algorithm > 中定義的reverse函式用於反轉在[first,last)範圍內的順序

template

void reverse (bidirectionaliterator first,bidirectionaliterator last);

例如,交換vector容器中元素的順序

vectorv=;

reverse(v.begin(),v.end());//v的值為5,4,3,2,1

當然,你也可以通過它方便的反轉string類的字串

string str="c++reverse";

reverse(str.begin(),str.end());//str結果為esrever++c

該函式等價於通過呼叫iter_swap來交換元素位置

template void reverse (bidirectionaliterator first, bidirectionaliterator last)

}

標準庫的begin()和end()函式是c++11新標準引入的函式,可以對陣列型別進行操作,返回其首尾指標,對標準庫容器操作,返回相應迭代器。

標準庫容器的begin()和end()成員函式屬於對應類的成員,返回的是物件容器的首尾迭代器。

試了一下,begin和end與vector容器搭配起來,再與reverse在一起使用,超好用!!!

**1,這是以前的**

//pat1008v1

#include int main()

a[0]=temp; }

for(i=0;i可以看出來具有初步的演算法思想,但是**簡潔性和凝練度需要提高。另外從除錯的注釋能夠看出來,**能力還不夠。

**2,現在的**

#include using namespace std;

int main();

for(int i=0;i>a[i];

for(int i=0;i0;j--) a[j]=a[j-1]; //從倒數第二位開始依次後移一位

a[0]=tmp; //挪出來的最後一位放到第一位上去

} for(int i=0;i**3,重新開闢陣列,將對應移動部分存起來,但不能完全ac

#include using namespace std;

int main();

for(int i=0;i>a[i];

if(m>0),c[n-m]=;

for(int i=0;i**4,注意m>n的情況,提高m>n時的移動效率

#include using namespace std;

int main();

for(int i=0;i>a[i];

if(m>0),c[n-m%n]=;

for(int i=0;i**5,通法的優化

#include using namespace std;

int main();

for(int i=0;i>a[i];

for(int i=0;i0;j--) a[j]=a[j-1]; //從倒數第二位開始依次後移一位

a[0]=tmp; //挪出來的最後一位放到第一位上去

} for(int i=0;i**6,偷懶做法,並沒有移動……

#include using namespace std;

int main();

for(int i=0;i>a[i];

if(m>0),c[n-m%n]=;

for(int i=0;i**7。使用庫函式

#include #include #include using namespace std;

int main()

for (int i = 0; i < n - 1; i++)

cout << a[i] << " ";

cout << a[n - 1];

return 0;

}

1008 陣列元素迴圈右移問題

這個題如果只是為了得到正確答案的話,使用直接列印的方法是最簡單地。但是如何能真正實現陣列元素的迴圈移位呢?要注意的是 當移位次數k大於陣列長度n的時候,跟移位k k n的效果是一樣的。我能想到的方法是,每次向右移一位,移動n次,實現方法如下 include void shiftright int a...

1008 陣列元素迴圈右移問題

乙個陣列a中存有n n 0 個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向右移m m 0 個位置,即將a中的資料由 a0a1 an 1 變換為 an m an 1 a0 a1 an m 1 最後m個數迴圈移至最前面的m個位置 如果需要考慮程式移動資料的次數盡量少,要如何設計移動的方法?輸入格...

1008 陣列元素迴圈右移問題

題目是pat乙級 思路 老問題了。只要把陣列進行三次翻轉就可以了,具體見程式。訓練目的 掌握迴圈移動的快速方法 順便了解 reverse演算法 題目描述 乙個陣列a中存有n n 0 個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向右移m m 0 個位置,即將a中的資料由 a0a1 an 1 變...