LeetCode 189. Rotate Array

来源:互联网 发布:sql看什么书 编辑:程序博客网 时间:2024/04/30 03:15

尽量用多种方法解题,至少有三种方法可以解决这个问题。参考了网上别人的方法。


1. 三次reverse, O(1)空间实现:

class Solution{public:void rotate(int nums[], int n, int k){if (n==0 || (k%=n)==0){return;}reverse(nums, nums+n-k);reverse(nums+n-k, nums+n);reverse(nums, nums+n);}};

下面是三次reverse算法不完全的证明:

1.1 公式

在区间[x, x+length)区间中,翻转下标为i的数,新的下标i'满足i - x = x+length-1 - i' => i' = 2x + length - i - 1.

1.2 将数据分为两段:[0, 1, ..., n-k) 和 [n-k, n) 

1.2.1 我们在这里只考虑后半段,对给定的n-k<= i < n. 

在这段代码中,只有第2\3个reverse才会影响它的位置。为直观起见,我们将nums(内存地址偏移)拿掉:

1) 第二条reverse(n-k, n): 这个i将会被移动到i' = 2(n-k) + k - i - 1 = 2n - k - i - 1的位置

2) 第三条reverse(0, n): 这个i'将会被移动到i'' = 2*0 + n - (2n - k - i - 1) - 1 = i + k - n的位置上

所以下标为i的元素,经这样reverse后将会出现在i + k - n的位置上,满足题意。


2. 每次只移动之前未移动过的元素,O(1)空间实现。代码:

class Solution{public:void rotate(int nums[], int n, int k){if (n==0 || (k%=n)==0){return;}int cur_index = 0;int flag = 0;int previous_value = nums[n - k];for (int i = 0; i < n; ++ i){int tmp = nums[cur_index];nums[cur_index] = previous_value;previous_value = tmp;flag = (flag + k) % n;if (flag == 0){cur_index = (cur_index + 1) % n;previous_value = nums[cur_index];}cur_index = (cur_index + k) % n;}}};

3. 最笨的O(n)空间实现:

class Solution {public:    void rotate(int nums[], int n, int k)     {        int new_nums[n];        for (int i = 0; i < n; ++ i)        {        new_nums[(i+k)%n] = nums[i];        }        memcpy(nums, new_nums, n * sizeof(int));    }};


0 0
原创粉丝点击