1. 程式人生 > >LeetCode演算法題-Rotate Array(Java實現)

LeetCode演算法題-Rotate Array(Java實現)

這是悅樂書的第184次更新,第186篇原創

01 看題和準備

今天介紹的是LeetCode演算法題中Easy級別的第43題(順位題號是189)。給定一個數組,將陣列向右旋轉k步,其中k為非負數。例如:

輸入:[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]

輸入:[ - 1,-100,3,99],k = 2
輸出:[3,99,-1,-100]
說明:
向右旋轉1步:[99,-1,-100,3]
向右旋轉2步:[3,99,-1,-100]

本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。

02 第一種解法

我們先看下原陣列依次旋轉7步的結果

[1,2,3,4,5,6,7]

[7,1,2,3,4,5,6]
[6,7,1,2,3,4,5]
[5,6,7,1,2,3,4]
[4,5,6,7,1,2,3]
[3,4,5,6,7,1,2]
[2,3,4,5,6,7,1]
[1,2,3,4,5,6,7]

我們可以發現旋轉是有周期性的,週期是陣列的長度,所以陣列反轉的次數是可控制的,只需旋轉k對陣列長度取餘數次即可。

最直接的辦法就是使用兩層迴圈,外層控制旋轉次數,內層控制元素交換位置。

public void rotate(int[] nums, int k) {
    if (k % nums.length != 0) {
        int pre, tem;
        for (int i=0; i < k % nums.length; i++) {
            pre = nums[nums.length-1];
            for (int j=0; j<nums.length; j++) {
                tem = nums[j];
                nums[j] = pre;
                pre = tem;
            }
        }
    }
}

此解法時間複雜度為O(n*k),空間複雜度為O(1)。

03 第二種解法

新建一個大小和nums一樣的陣列,然後將旋轉後的元素放入新的陣列中,再遍歷新陣列賦值給nums。新陣列的元素從nums的長度先減去k再加上i開始,直到i不小於k為止,這些元素是需要拿到陣列前面去的。當i大於等於k時,新陣列的元素要從nums的第1位開始,也就是將原陣列前面的元素放到後面來。

對於k的值,先判斷對陣列長度取餘是否等於0,不等於0後才會開始下一步操作。

public void rotate2(int[] nums, int k) {
    if (k % nums.length != 0) {
        k = k % nums.length;
        int pointer = 0;
        int[] tem = new int[nums.length];
        for (int i=0; i < tem.length; i++) {
            if (i<k) {
                tem[i] = nums[tem.length-k+i];
            } else {
                tem[i] = nums[pointer++];
            }
        }
        for (int j=0; j<nums.length; j++) {
            nums[j] = tem[j];
        }
    }
}

此解法的時間複雜度是O(n),空間複雜度是O(n),因為使用了新的陣列。

04 第三種解法

先通過一個小例子來說明:

nums = {1,2,3,4,5,6,7},k = 3,

先反轉其全部元素,變成{7,6,5,4,3,2,1}

再反轉前3個元素,變成{5,6,7,4,3,2,1}

再反轉後4個元素,變成{5,6,7,1,2,3,4}

這樣就能夠得到答案了。

public void rotate3(int[] nums, int k) {
    if (k % nums.length != 0) {
        k %= nums.length;
        reverse(nums, 0, nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }
}

public void reverse(int[] nums, int start, int end) {
    while (start < end) {
        int temp = nums[start];
        nums[start] = nums[end];
        nums[end] = temp;
        start++;
        end--;
    }
}

此解法的時間複雜度是O(n),空間複雜度是O(1)。

05 小結

演算法專題目前已連續日更超過一個月,演算法題文章43+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。

以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!