题目描述(简单难度)

189. Rotate Array - 图1

转动数组,将数组的最后一个元素移动到开头,重复操作 k 次。

解法一

完全按照题目的意思,每次把末尾的元素移动到开头,当然移动前需要把所有元素后移一位,把第一个位置腾出来。

此外,如果 k 大于数组的长度,k 是等效于 k % n 的。举个例子,nums = [1 2 3]k = 4,操作 4 次和操作 4 % 3 = 1 次是一样的结果。

  1. public void rotate(int[] nums, int k) {
  2. int n = nums.length;
  3. k = k % n;
  4. for (int i = 0; i < k; i++) {
  5. int temp = nums[n - 1];
  6. for (int j = n - 1; j > 0; j--) {
  7. nums[j] = nums[j - 1];
  8. }
  9. nums[0] = temp;
  10. }
  11. }

时间复杂度:O(kn)

空间复杂度:O(1)

解法二

空间换时间,解法一中每个元素都需要移动 k 次,因为最后一个元素移到第一个位置的话,就进行了整体后移。不然的话,第一个位置原来的数就会被覆盖掉。

我们可以申请一个和原数组等大的数组,复制之前所有的值。这样的话,我们就可以随心所欲的在原数组上赋值了,不需要考虑值的丢失。

  1. public void rotate(int[] nums, int k) {
  2. int n = nums.length;
  3. k = k % n;
  4. int[] numsCopy = new int[n];
  5. for (int i = 0; i < n; i++) {
  6. numsCopy[i] = nums[i];
  7. }
  8. //末尾的 k 个数复制过来
  9. for (int i = 0; i < k; i++) {
  10. nums[i] = numsCopy[n - k + i];
  11. }
  12. //剩下的数复制过来
  13. for (int i = k; i < n; i++) {
  14. nums[i] = numsCopy[i - k];
  15. }
  16. }

时间复杂度:O(n)

空间复杂度:O(n)

解法三

上边的解法都是直接可以想到的,写完之后看了 官方 提供的解法,下边分享一下。

换一种题目的理解方式。

189. Rotate Array - 图2

把数组看成一个圆环,而 k 的含义其实就是所有数字顺时针移动 k 个位置。

如果 k = 2,那么含义就是 1 放到 3 的位置,3 放到 5 的位置…

当然程序上,如果 1 放到 3 的位置,3 就会被覆盖了,我们应该用一个变量 pre 存储当前位置被占用的数字。

思想就是上边的了,代码的话可能会有不同的写法,下边的供参考。

  1. public void rotate(int[] nums, int k) {
  2. int n = nums.length;
  3. k = k % n;
  4. if (k == 0) {
  5. return;
  6. }
  7. int count = 0; //记录搬移了多少个数字
  8. int start = 0;
  9. int current = start;
  10. int pre = nums[current];
  11. while (true) {
  12. do {
  13. //要移动过去的位置
  14. int next = (current + k) % n;
  15. //数字做缓存
  16. int temp = nums[next];
  17. //将数字搬过来
  18. nums[next] = pre;
  19. pre = temp;
  20. //考虑下一个位置
  21. current = next;
  22. count++;
  23. //全部数字搬移完就结束
  24. if (count == n) {
  25. return;
  26. }
  27. } while (start != current);
  28. //这里是防止死循环,因为搬移的位置可能会回到最开始的位置, 所以我们 start++, 继续搬移其他组
  29. start++;
  30. current = start;
  31. pre = nums[current];
  32. }
  33. }

时间复杂度:O(n),每个数字仅搬移一次。

空间复杂度:O(1)

解法四

依旧是参考 官方 题解。

看具体的例子,1 2 3 4 5k = 2

转换后最终变成 4 5 1 2 3

其实可以分三步完成。

整体逆序 5 4 3 2 1

k 个再逆序 4 5 3 2 1

后边的再逆序 4 5 1 2 3

  1. public void rotate(int[] nums, int k) {
  2. int n = nums.length;
  3. k = k % n;
  4. reverse(nums, 0, n - 1);
  5. reverse(nums, 0, k - 1);
  6. reverse(nums, k, n - 1);
  7. }
  8. private void reverse(int[] nums, int start, int end) {
  9. while (start < end) {
  10. int temp = nums[start];
  11. nums[start] = nums[end];
  12. nums[end] = temp;
  13. start++;
  14. end--;
  15. }
  16. }

时间复杂度:O(n)

空间复杂度:O(1)

解法一、解法二就是对题目最简单的理解,解法三和解法四是进一步对题目的剖析,很厉害。

windliang wechat

添加好友一起进步~

如果觉得有帮助的话,可以点击 这里 给一个 star 哦 ^^

如果想系统的学习数据结构和算法,强烈推荐一个我之前学过的课程,可以点击 这里 查看详情