繁体   English   中英

Java - 旋转数组

[英]Java - Rotating array

所以,我们的目标是旋转阵列右侧的元素a时代。 举个例子; 如果a==2 ,则array = {0,1,2,3,4}将变为array = {3,4,0,1,2}

这是我所拥有的:

for (int x = 0; x <= array.length-1; x++){
    array[x+a] = array[x];
}

然而,当[x+a]大于数组的长度时,这无法解释。 我读到我应该将较大的存储在不同的数组中,但将a视为变量,我不确定这是最好的解决方案。 提前致谢。

将模数组长度添加到您的代码中:

// create a newArray before of the same size as array

// copy
for(int x = 0; x <= array.length-1; x++){
  newArray[(x+a) % array.length ] = array[x];
}

您还应该创建一个要复制到的新Array ,这样您就不会覆盖稍后需要的值。

如果您不想重新发明轮子(也许这是一个练习,但知道它会很好),您可以使用Collections.rotate

请注意,它需要一个对象数组,而不是原始数据类型(否则您将在列表中交换数组本身)。

Integer[] arr = {0,1,2,3,4};
Collections.rotate(Arrays.asList(arr), 2);
System.out.println(Arrays.toString(arr)); //[3, 4, 0, 1, 2]

Arraycopy 是一项昂贵的操作,无论是时间还是内存方面。 以下将是一种在不使用额外空间的情况下旋转数组的有效方法(与创建相同大小的新数组的公认答案不同)。

public void rotate(int[] nums, int k) { // k = 2
    k %= nums.length;
    // {0,1,2,3,4}

    reverse(nums, 0, nums.length - 1); // Reverse the whole Array
    // {4,3,2,1,0}

    reverse(nums, 0, k - 1); // Reverse first part (4,3 -> 3,4)
    // {3,4,2,1,0}

    reverse(nums, k, nums.length - 1); //Reverse second part (2,1,0 -> 0,1,2)
    // {3,4,0,1,2}
}

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--;
    }
}

我认为最快的方法是使用System.arrayCopy()这是本机方法:

int[] tmp = new int[a];
System.arraycopy(array, array.length - a, tmp, 0, a);
System.arraycopy(array, 0, array, a, array.length - a);
System.arraycopy(tmp, 0, array, 0, a);

它还重用现有数组。 在某些情况下它可能是有益的。 最后一个好处是临时数组的大小小于原始数组。 因此,当a较小时,您可以减少内存使用量。

另一种方法是使用System.arraycopy 进行复制。

    int[] temp = new int[array.length];
    System.arraycopy(array, 0, temp, a, array.length - a);
    System.arraycopy(array, array.length-a, temp, 0, a);
int[] rotate(int[] array, int r) {
    final int[] out = new int[array.length];
    for (int i = 0; i < array.length; i++) {
        out[i] = (i < r - 1) ? array[(i + r) % array.length] : array[(i + r) % array.length];
    }
    return out;
}

下面的rotate方法将与Collections类的rotate方法与List接口的subList方法结合使用完全相同,即rotate(n,fromIndex,toIndex,dist),其中n是一个整数数组,将给出结果与 Collections.rotate (Arrays.asList (n).subList (fromIndex, toIndex), dist) 相同,其中 n 是整数数组。

首先创建一个交换方法:

public static void swap (int[] n, int i, int j){

   int tmp = n[i];
   n[i] = n[j];
   n[j] = tmp;
}

然后创建旋转方法:

public static void rotate (int[] n, int fromIndex, int toIndex, 
int dist){

   if(fromIndex > toIndex)

      throw new IllegalArgumentException ("fromIndex (" + 
         fromIndex + ") > toIndex (" + toIndex + ")");

   if (fromIndex < toIndex){

      int region = toIndex - fromIndex;
      int index;

      for (int i = 0; i < dist % region + ((dist < 0) ? region : 0); 
              i++){

         index = toIndex - 1;
     
         while (index > fromIndex)

            swap (n, index, --index);
       }
   }
}

问题: https : //www.hackerrank.com/challenges/ctci-array-left-rotation
解决方案:这就是我尝试复杂度为 o(n) 的 arrayLeftRotation 方法的方法

  • 从 k 索引到 (length-1) 循环一次
  • 0 到第 k 个索引的第二次

    public static int[] arrayLeftRotation(int[] a, int n, int k) {
    int[] resultArray = new int[n];
    int arrayIndex = 0;
    //第一个 nk 个索引将在此循环中填充
    for(int i = k ; i resultArray[arrayIndex] = a[i];
    数组索引++;
    }
    // 将在此循环中填充第 2 个索引
    for(int j=arrayIndex ; j<(arrayIndex+k); j++){
    resultArray[j]=a[j-(nk)];
    }
    返回结果数组;
    }

封装在方法中的 Java 解决方案:

public static int[] rotate(final int[] array, final int rIndex) {
    if (array == null || array.length <= 1) {
        return new int[0];
    }

    final int[] result = new int[array.length];
    final int arrayLength = array.length;

    for (int i = 0; i < arrayLength; i++) {
        int nIndex = (i + rIndex) % arrayLength;
        result[nIndex] = array[i];
    }
    return result;
}

对于左旋转它非常简单

取数组长度和要移动的位置数之间的差值。

例如

int k = 2;
int n = 5;

int diff = n - k;

int[] array = {1, 2, 3, 4, 5};
int[] result = new int[array.length];
System.arraycopy(array, 0, result, diff, k);
System.arraycopy(array, k, result, 0, diff);

// 打印输出

package com.array.orderstatistics;

import java.util.Scanner;

public class ArrayRotation {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int r = scan.nextInt();
        int[] a = new int[n];
        int[] b = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = scan.nextInt();
        }
        scan.close();

        if (r % n == 0) {
            printOriginalArray(a);
        } else {
            r = r % n;
            for (int i = 0; i < n; i++) {
                b[i] = a[(i + r) < n ? (i + r) : ((i + r) - n)];
                System.out.print(b[i] + " ");
            }
        }
    }

    private static void printOriginalArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
    }

}

ruby中,可以在一行中旋转一个数组。

def array_rotate(arr)
   i, j = arr.length - 1, 0
   arr[j],arr[i], i, j = arr[i], arr[j], i - 1, j + 1 while(j<arr.length/2)
   puts "#{arr}"
end

问题:给定特定距离旋转数组。 方法 1:将 int 数组转换为 ArrayList。 然后使用 Collections.rotate(list,distance)。

class test1 {
    public static void main(String[] args) {

        int[] a = { 1, 2, 3, 4, 5, 6 };

        List<Integer> list = Arrays.stream(a).boxed().collect(Collectors.toList());

        Collections.rotate(list, 3);
        System.out.println(list);//[4, 5, 6, 1, 2, 3]

    }// main
}

时间复杂度 = O(n)

空间复杂度 = O(1)

该算法从数组的第一个元素 (newValue) 开始,并将其放置在旋转后的位置 (newIndex)。 位于 newIndex 的元素变为 oldValue。 之后,oldValue 和 newValue 被交换。

这个过程重复长度次。

该算法基本上围绕数组反弹,将每个元素放置在新位置。

unsigned int computeIndex(unsigned int len, unsigned int oldIndex, unsigned int times) {
    unsigned int rot = times % len;
    unsigned int forward = len - rot;

    // return (oldIndex + rot) % len; // rotating to the right
    return (oldIndex + forward) % len; // rotating to the left
}

void fastArrayRotation(unsigned short *arr, unsigned int len, unsigned int rotation) {
    unsigned int times = rotation % len, oldIndex, newIndex, length = len;
    unsigned int setIndex = 0;
    unsigned short newValue, oldValue, tmp;

    if (times == 0) {
        return;
    }

    while (length > 0) {
        oldIndex = setIndex;
        newValue = arr[oldIndex];
        while (1) {
            newIndex = computeIndex(len, oldIndex, times);
            oldValue = arr[newIndex];
            arr[newIndex] = newValue;

            length--;

            if (newIndex == setIndex) { // if the set has ended (loop detected)
                break;
            }

            tmp = newValue;
            newValue = oldValue;
            oldValue = tmp;

            oldIndex = newIndex;
        }
        setIndex++;
    }
}

以下例程在 java 中旋转数组:

public static int[] rotateArray(int[] array, int k){
    int to_move = k % array.length;
    if(to_move == 0)
      return array;
    for(int i=0; i< to_move; i++){
      int temp = array[array.length-1];
      int j=array.length-1;
      while(j > 0){
        array[j] = array[--j];
      }
      array[0] = temp;
    }
    return array;
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM