一尘不染

如何在不增加堆内存的情况下循环移位数组?

algorithm

如何编写一个shift(int* arr, int k)将数组循环移位某个整数k 的函数?我不能说堆中的“ malloc”内存。

例如,使用伪代码shift([1, 2, 3, 4], 2)返回[3, 4, 1, 2],然后shift([3, 1, 5, 5], 103)返回[1, 5, 5, 3]。我已经尝试过使用模数来达到这种效果,如该Java程序所示,在该程序中,我基本上遍历了一半的数组和交换值。

public static int* shift(int* arr, int k) {
  int half_array_len = arr.length / 2;
  for (int i = 0; i < half_array_len; ++i) {
    // Swap!
    int newIndex = (i + k) % arr.length;
    int temp = arr[i];
    arr[i] = arr[newIndex];
    arr[newIndex] = arr[i];
  }
  return arr;
}

但是,我相信此函数仅适用于偶数长度的数组。

如何实现shift任何长度的数组?答案可以使用您想要的任何语言(Java,C ++,Ook
Ook!
等)。


阅读 232

收藏
2020-07-28

共1个答案

一尘不染

(以前曾被问过几次。)基本上,在Bentley的“ Programming
Pearls”(杂耍,反转和块交换算法)中描述并分析了三种专用于解决此问题的经典就地算法。这些幻灯片对它们进行了足够详细的描述

http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf

最简单的算法是逆向算法。只需反转整个数组,然后分别反转每个[n-k]和[k]块。做完了 (从哪个端开始计算[k]块取决于移位的方向。)

当然,标准化第k一个是有意义的,也就是说,k = k % n要确保k小于n

PS在C
++中,答案将是使用std::rotate,它确实可以满足您的需求。但是我怀疑这是您寻求的答案。尽管您可能想看看的某些实现std::rotate(如果只是发现它们通常使用反向算法:)

2020-07-28