LeetCode-探索-初級-陣列-旋轉陣列-java
旋轉陣列
給定一個數組,將陣列中的元素向右移動 k 個位置,其中 k 是非負數。
示例 1:
輸入:[1,2,3,4,5,6,7]
和 k = 3 輸出:[5,6,7,1,2,3,4]
解釋: 向右旋轉 1 步:[7,1,2,3,4,5,6]
向右旋轉 2 步:[6,7,1,2,3,4,5]
向右旋轉 3 步:[5,6,7,1,2,3,4]
示例 2:
輸入: [-1,-100,3,99]
和 k = 2
輸出: [3,99,-1,-100]
解釋:
向右旋轉 1 步: [99,-1,-100,3]
向右旋轉 2 步: [3,99,-1,-100]
說明:
- 儘可能想出更多的解決方案,至少有三種不同的方法可以解決這個問題。
- 要求使用空間複雜度為 O(1) 的原地演算法。
題目讓我們至少使用三種方法,我們就使用三種方法吧~
方法一:
還記得我們交換兩個int的程式碼嗎?
int temp = a1;
a1 = a2;
a2 = temp;
是這樣吧~
我們以nums=[1, 2, 3, 4, 5, 6, 7],k=3為例
第一次變換:1 2 3 1(4) 5 6 7
第二次變換:1 2 3 1(4) 2(5) 6 7
第三次變換:1 2 3 1(4) 2(5) 3(6) 7
第四次變換:1 2 3 1(4) 2(5) 3(6) 4(7)
我們可以看出:我們需要一個k長度的陣列儲存中間因為1 2 3覆蓋掉的4 5 6;可以看出,在第四次變換中,我們的4又重新派上了用場。
程式碼如下:
public void rotate(int[] nums, int k) { if (k == nums.length || k == 0 || nums.length == 1) return ; k = k % nums.length; int[] tempArray = new int[k]; //store the temp elements for (int i = 0; i < k; i++) tempArray[i] = nums[i]; //init tempArray int temp = 0; int index = 0; int tempIndex = 0; for (int i = 0; i < nums.length; i++) { index = (i + k) % nums.length; temp = nums[index]; nums[index] = tempArray[tempIndex]; tempArray[tempIndex] = temp; tempIndex = (tempIndex + 1) % k; } }
方法二:
在第一種方法中,我們需要不停變換之前的臨時陣列tempArray中的元素,好的,我不想變。
我要考慮另外的思路。
還是上面的例子nums=[1, 2, 3, 4, 5, 6, 7],k=3
初始狀態:1 2 3 4 5 6 7
最終狀態:5 6 7 1 2 3 4
是不是發現了些什麼?
最後的三個元素移動到了前面,前面的元素移動到了後面
像極了將前面的元素刪除之後再插入到後面(在順序表中)【但是我並沒有這樣寫】
程式碼如下:
public void rotate3(int[] nums, int k) {
k = k % nums.length;
if (k == 0)
return ;
int[] temp = new int[k];
int index = 0;
for (int i = nums.length - k; i < nums.length ; i ++)
temp[index ++] = nums[i];
//end store elements
for (int i = nums.length - k - 1 ; i >= 0 ; i --)
nums[i+ k] = nums[i];
for (int i = 0 ; i < k ; i ++)
nums[i] = temp[i];
}
方法三:
emm,為什麼要利用一個數組儲存?不能用一個int的量嗎?
可以。
仍然是上面的例子:nums=[1, 2, 3, 4, 5, 6, 7],k=3
我們進行如下的變換:
5(1) 6(2) 7(3) 1(4) 2(5) 3(6) 4(7)
大變換是從nums[0] to nums[3] to nums[6] to nums[2] to nums[5] to nums[1] to nums[4] to nums[0](end)
但是這並不絕對,因為有可能出現nums=[1, 2, 3, 4, 5, 6],k=2的情況,如果還是僅僅從0開始,就會發生如下情況
nums[0] to nums[2] to nums[4] to nums[0](end)
無法完成一次整體的迴圈
針對這種情況,就要依次從0-k-1作為起點進行k次大的變換
程式碼如下:
public void rotate2(int[] nums, int k) {
k = k % nums.length;
if (k == 0)
return ;
BitSet bitSet = new BitSet(nums.length);
int prev;
int next;
int nextIndex = 0;
for (int i = 0 ; i < k ; i ++) {
next = nums[i]; //每一次開始起始的值都要發生變化
for (int index = i ; !bitSet.get(index) ; index = nextIndex) {
nextIndex = (index + k) % nums.length; //下一個位置
prev = nums[nextIndex];
nums[nextIndex] = next;
next = prev;
bitSet.set(index); //標記當前位數
}
}
}
bitset用於記錄那些值是被替換過的,下一次進行迴圈的時候就不會重複操作。