LeetCode(初級演算法)陣列篇---旋轉陣列
阿新 • • 發佈:2019-01-03
題目
將包含 n 個元素的陣列向右旋轉 k 步。
例如,如果 n = 7 , k = 3,給定陣列 [1,2,3,4,5,6,7]
,向右旋轉後的結果為 [5,6,7,1,2,3,4]
。
注意:
儘可能找到更多的解決方案,這裡最少有三種不同的方法解決這個問題。
提示:
要求空間複雜度為 O(1)
解析
做這道題之前需要知道,k是以一個數組長度為迴圈週期。
所以無論是什麼方法,都應該在開始時就完成
k=k%nums.length;
方法一
- 第一種方法是最為直接的,按照邏輯上對旋轉怎麼理解,就讓程式怎麼執行
- 需要一個臨時變數
- 這種方法簡單易懂,但==效率很低==
Example:每旋轉1次的執行過程
1)先將最後一個儲存到臨時變數
1 2 3 4 5 6 7 8 [8]---臨時變數
2)位移
_ 1 2 3 4 5 6 7 [8]---臨時變數
3) 將臨時變數放到第一個
8 1 2 3 4 5 6 7
程式碼
public class Solution {
@Test
public void rotate(int[] nums, int k) {
k = k % nums.length;
for (int count = 0; count < nums.length; count++) { //執行趟數
int temp = nums[nums.length - 1];
for (int j = nums.length - 1; j > 0; j--) {
nums[j] = nums[j - 1];
}
nums[0] = temp;
}
}
}
方法二
第二種方法用得是正則表示式,通過StringBuffer將旋轉後的結果新增入緩衝區,再用Matcher進行篩選
這種方法比較適用於==陣列長度較大的旋轉==,時間複雜度較高,但空間複雜度較低
public class Solution3 { private static String REGEX = "[+-]?\\d+"; public void rotate(int[] nums, int k) { k=k%nums.length; StringBuffer str = new StringBuffer(); int index = nums.length-k; //time在這裡作為趟數,也作為偏移量 for(int time=0;time<nums.length;time++) { str.append(nums[(index + time) %nums.length]); str.append(' '); } //編譯正則表示式 Pattern p =Pattern.compile(REGEX); //進行匹配 Matcher m =p.matcher(str); int i=0; while(m.find()) { nums[i++]= Integer.valueOf(str.substring(m.start(),m.end())); } } }
方法三
- 第三種方法,是通過呼叫System.arraycopy和使用Arrays.copyOfRange完成,對陣列內容的複製和移動
- 這種方法執行==速度很快(System.arraycopy 是 本地方法)==,但是空間複雜度會比較高
程式碼
public void rotate(int[] nums, int k) {
k=k%nums.length;
// 返回 下標 為 nums.length-k到最後一個元素的子陣列temp
int temp[] = Arrays.copyOfRange(nums,nums.length-k ,nums.length);
// 將剩餘的元素複製到旋轉後的位置
System.arraycopy(nums, 0, nums, k, nums.length-k);
// 將temp複製到nums的開頭
System.arraycopy(temp, 0,nums , 0, k);
}
圖解
1) 初始狀態
nums: 1 2 3 4 5 6 7 8
k: 3
2) 取出子集
nums: 1 2 3 4 5 6 7 8
temp: 6 7 8
3) 將剩餘的元素複製到旋轉後的位置
nums: 1 2 3 1 2 3 4 5
temp: 6 7 8
4) 將temp複製到nums的開頭
nums: 6 7 8 1 2 3 4 5
拓展
陣列的複製
- System.arrayscopy(源陣列,起始位置,目標陣列,起始位置,複製長度)—-本地方法
*可以複製到自己身上
Eg:System.arrayscopy(obj,0,obj,3,3):表示數組裡的前三個字元向右移動3個位置
Arrays.copyOf(目標陣列,新的長度)—– 返回新陣列
Arrays.copyOfRang(目標陣列,起始位置,結束位置)—–返回新陣列
與System.arrayscopy不同的是:==複製區間是從起始位置,到結束位置的前一個元素==