Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中数组反转的快速算法_Java_Algorithm - Fatal编程技术网

Java中数组反转的快速算法

Java中数组反转的快速算法,java,algorithm,Java,Algorithm,我已经编写了代码来反转具有时间复杂性的数组:O(n) 有没有更快的方法 我的代码: void reverseArray(int arr[], int start, int end){ int temp; if(start >= end) return; temp = arr[start]; arr[start] = arr[end]; arr[end] = temp;

我已经编写了代码来反转具有时间复杂性的数组:O(n)

有没有更快的方法

我的代码:

 void reverseArray(int arr[], int start, int end){
        int temp;
        if(start >= end)
            return;
        temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        reverseArray(arr, start+1, end-1);   
    }

从字面上讲,反转内存中的元素的速度不可能比O(n)快。但是,可以使索引数组的包装器类反转。因此,事实上,您不反转数组,而只向后访问元素

您拥有的代码是O(n),但由于递归,代码很糟糕。把它弄平,你会得到一些好处

public static void reverseArray(int arr[], int start, int end)
{
    int len = end - start;
    if(len <= 0) return;

    int len2 = len >> 1;
    int temp;

    for (int i = 0; i < len2; ++i)
    {
        temp = arr[start + i];
        arr[start + i] = arr[end - i - 1];
        arr[end - i - 1] = temp;
    }
}
public static void reversearlay(int arr[],int start,int end)
{
int len=结束-开始;
如果(len>1;
内部温度;
对于(int i=0;i
您使用的递归不如循环快。您仍然是O(n),但使用循环的时间更快。类似于:

static void reverseArray(int arr[]){
   for (int start=0,end=arr.length-1;start<=end;start++,end--) {
      int temp = arr[start];
      arr[start] = arr[end];
      arr[end] = temp;
   }
}
static void reversearlay(int arr[]){

对于(int start=0,end=arr.length-1;start如果您使用静态数组,因为您需要访问每个元素一次才能将其反转,所以复杂性不比n小


但是,如果您使用双链接列表,则通过定义,您可以从两个方向访问元素。从头到尾和从尾到头,因为所使用的节点类中有双指针。因此,甚至不需要使用反向,而是在需要时从尾到头进行迭代

您可以使用一些中介功能:

int rev(int i) {
    return arr.length - i - 1;
}
//...
arr[rev(i)] = 5; // reverse reference

递归vs迭代。函数调用(递归)成本周期。因此,对于此解决方案,我将采用迭代方法。其他需要注意的事项是:偶数/奇数大小的数组、空数组、只有1项的数组。未经测试的解决方案是:

void reverseArray(int arr[]){

  //check input
  if(arr.length <= 1){
    return;
  }

  int arrLength = arr.length;
  int swpIndex;

  for (int i = 0; i < arrLength / 2 - 1; i++){
    swpIndex = arrLength - i - 1;

    swp = arr[i];
    arr[i] = arr[swpIndex]; 
    arr[swpIndex] = swp;
  }
}
void reversearlay(int arr[]){
//检查输入

if(arr.length)可能不会更快,但为什么不将其转换为列表并使用Collections.reverse()呢?我通常相信编写Java的人比我更聪明,而且它使代码更具可读性。我不确定它是否会运行得更快,但为什么不使用一个简单的while循环,它有两个索引,一个从左开始,一个从右开始,而不是对函数的递归调用呢?不要重新发明轮子,使用
arrayUtils.反向(int[]arr)
来自apache库。@user2336315-完全同意..在递归中,大小越大,发生StackOverflower错误的可能性越高。请参阅,和。递归的主要问题是所需的内存。它既慢又占用更多内存,而且迭代深度有限,而循环则不然。@kai-Tim是对的…Recursion的速度较慢,因为每次递归调用函数时,堆栈上都会发生太多的操作。很高兴知道为什么我得到了向下投票:s@TheLostMind我知道,我只想指出还有一个记忆问题。这不是我的反对票:)我喜欢你对包装类的建议。你也不需要反转数组,你只需要编写一个包装类,反向索引数组(如)。Dukeling是的,但是,算法复杂度仍然是O(n)。另一方面,当使用双链接列表时,您不必执行该步骤。因此,该步骤的复杂性仅为O(1)。您只需直接从尾部到头部访问元素。不,您可以将数组分配给包装类的一个成员(也可以从包装类开始),并简单地设置“反向”包装类中的标志(指示访问器和变异器应该反向索引数组),都是O(1)。我的意思是@Dukeling,所以当数组被标记为反向时,以另一种方式访问数组。在给出的示例中,复杂性确实是O(1)。感谢您的说明。