【问题标题】:Algorithms - Circular Array Rotation算法 - 圆阵列旋转
【发布时间】:2017-07-25 00:43:51
【问题描述】:

这种圆形阵列旋转的线性复杂度实现是否正确?

n = 元素数 k = 转数

    int write_to     = 0;
    int copy_current = 0;
    int copy_final   = a[0];
    int rotation     = k;
    int position     = 0;

    for (int i = 0; i < n; i++) {
        write_to     = (position + rotation) % n;
        copy_current = a[write_to];
        a[write_to]  = copy_final;
        position     = write_to;
        copy_final   = copy_current;
     }

【问题讨论】:

  • 嗯,复杂性肯定是线性的。但是,如果您希望通过将数组中的值全部移动#rotation 位置来旋转数组中的值,传统上被描述为圆形旋转,那么当这不是您最终会得到的结果时,您会感到惊讶。
  • @vadim:该问题的公认答案当然是正确的,但更漂亮的解决方案是: 1. 反转前 ​​k 个元素。 2.反转其余元素。 3. 反转整个数组。 (所有的反转都在原地。)
  • 是的。我喜欢! :)

标签: c++ arrays algorithm


【解决方案1】:

没有。

考虑这个例子。

#include <iostream>

int main(void) {
    int n = 6;
    int k = 2;
    int a[] = {1, 2, 3, 4, 5, 6};

    int write_to     = 0;
    int copy_current = 0;
    int copy_final   = a[0];
    int rotation     = k;
    int position     = 0;

    for (int i = 0; i < n; i++) {
        write_to     = (position + rotation) % n;
        copy_current = a[write_to];
        a[write_to]  = copy_final;
        position     = write_to;
        copy_final   = copy_current;
     }

    for (int i = 0; i < n; i++) {
        std::cout << a[i] << (i + 1 < n ? ' ' : '\n');
    }
    return 0;
}

预期结果:

5 6 1 2 3 4

实际结果:

3 2 1 4 1 6

【讨论】:

    【解决方案2】:

    在 std::array 上使用 stl::rotate,你可以左旋转,比如 2,如下:

    std::array<int, 6> a{1, 2, 3, 4, 5, 6};
    std::rotate(begin(a), begin(a) + 2, end(a)); // left rotate by 2
    

    产生:3 4 5 6 1 2,或右旋,例如 2,如下:

    std::rotate(begin(a), end(a) - 2, end(a)); // right rotate by 2
    

    产生:5 6 1 2 3 4,具有线性复杂度。

    【讨论】:

      【解决方案3】:

      leftright 方向上将长度为n 的数组旋转k 次。

      代码是Java

      我定义了一个方向枚举:

      public enum Direction {
          L, R
      };
      

      使用timesdirection 旋转:

      public static final void rotate(int[] arr, int times, Direction direction) {
          if (arr == null || times < 0) {
              throw new IllegalArgumentException("The array must be non-null and the order must be non-negative");
          }
          int offset = arr.length - times % arr.length;
          if (offset > 0) {
              int[] copy = arr.clone();
              for (int i = 0; i < arr.length; ++i) {
                  int j = (i + offset) % arr.length;
                  if (Direction.R.equals(direction)) {
                      arr[i] = copy[j];
                  } else {
                      arr[j] = copy[i];
                  }
              }
          }
      }
      

      复杂度:O(n)。

      示例: 输入:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 旋转3left 输出:[4, 5, 6, 7, 8, 9, 10, 1, 2, 3]

      输入:[4, 5, 6, 7, 8, 9, 10, 1, 2, 3] 旋转3right 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

      【讨论】:

      • 虽然这可能会回答这个问题,但最好解释一下答案的基本部分,以及 OPs 代码可能存在什么问题。
      • 您没有回答问题(“圆形数组旋转的这种线性复杂度实现是否正确?”),只是提出了您对潜在问题的解决方案,没有任何评论。如果您解释原因和内容,我们将不胜感激。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      相关资源
      最近更新 更多