要求:設計乙個演算法,把乙個含有n個元素的陣列迴圈右移k位,要求時間複雜度為o(n),且只允許使用兩個附加變數。
不合題意的解法如下:
我們先試驗簡單的辦法,可以每次將陣列中的元素右移一位,迴圈k次。abcd1234→4abcd123→34abcd12→234abcd1→1234abcd。
版本1void
rightshift(
char
*arr,
intn,
intk)
}雖然這個演算法可以實現陣列的迴圈右移,但是演算法複雜度為o(k * n),不符合題目的要求,需要繼續往下探索。
分析與解法
假如陣列為abcd1234,迴圈右移4位的話,我們希望到達的狀態是1234abcd。不妨設k是乙個非負的整數,當k為負整數的時候,右移k位,相當於左移(-k)位。左移和右移在本質上是一樣的。
【解法一】
大家開始可能會有這樣的潛在假設,k
仔細觀察迴圈右移的特點,不難發現:每個元素右移n位後都會回到自己的位置上。因此,如果k >n,右移k-n之後的陣列序列跟右移k位的結果是一樣的。進而可得出一條通用的規律:右移k位之後的情形,跟右移k』= k %n位之後的情形一樣。
版本2void
rightshift(
char
*arr,
intn,
intk)
}可見,增加考慮迴圈右移的特點之後,演算法複雜度降為o(n
2),這跟k無關,與題目的要求又接近了一步。但時間複雜度還不夠低,接下來讓我們繼續挖掘迴圈右移前後,陣列之間的關聯。
【解法二】
假設原陣列序列為abcd1234,要求變換成的陣列序列為1234abcd,即迴圈右移了4位。比較之後,不難看出,其中有兩段的順序是不變的:1234和abcd,可把這兩段看成兩個整體。右移k位的過程就是把陣列的兩部分交換一下。變換的過程通過以下步驟完成:
1. 逆序排列abcd:abcd1234 → dcba1234;
2. 逆序排列1234:dcba1234 → dcba4321;
3. 全部逆序:dcba4321 → 1234abcd。
版本3reverse(
char
*arr,
intb,
inte)
}rightshift(
char
*arr,
intn,
intk)
陣列迴圈移位
陣列迴圈移位 對於存有n個整數的陣列,將其向左迴圈移動k個位置,x0,x1,xn 1 變換為 xk,xk 1,xn 1,x0,x1,xk 1 最直接的方法就是每次將首位的數放到乙個臨時的整型變數中,後面n 1個數一次左移,這樣需要k次才能完成,而每次的複雜度是o n 因此總共其複雜度是o k n 一...
陣列迴圈移位
題目 設計乙個演算法,把乙個含有n個元素的陣列迴圈右移k位,要求複雜度為o n 且只允許使用兩個變數 思考問題 1 考慮原始解法 直接迴圈移動陣列k次,則演算法複雜度為0 n k 使用額外兩個變數完成,顯然複雜度依賴於k的值,如果k n,則演算法複雜度大於或等於o n 2 2 考慮改進 原始演算法複...
陣列迴圈移位
問題描述 n個元素儲存於陣列a 0.n 1 中,求向右或向左迴圈移位 k k 0 位得到的新陣列a。1.迴圈右移 步驟 1 k k n 2 把序列分成前 n k 個數和後k個數兩組分別進行逆轉操作,如下圖 如下 void rightshift char a,int n,int k 其中reverse...