【问题标题】:Fast Algorithm in Java to Reverse an Array [duplicate]Java中用于反转数组的快速算法[重复]
【发布时间】:2014-01-28 04:31:23
【问题描述】:

我已编写代码来反转具有时间复杂度的数组: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);   
    }

【问题讨论】:

标签: java algorithm


【解决方案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;
    }
}

【讨论】:

  • 我喜欢你对包装类的建议
【解决方案2】:

您使用的递归不如循环快。您仍然是 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;
   }
}

对于这样的事情,你最好使用 Java 库中提供的方法来完成它。

【讨论】:

  • 递归的主要问题是需要的内存。
  • 它既慢又占用更多内存,而且迭代深度有限,而循环则不然。
  • @kai - Tim 是对的...递归比较慢,因为每次递归调用函数时堆栈上都会发生太多操作
  • 很高兴知道我为什么投了反对票:s
  • @TheLostMind 我知道,我只想指出也存在内存问题。那不是我的反对意见:)
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    如果您使用静态数组,因为您需要访问每个元素一次才能反转它,所以没有比 n 更复杂的复杂度。

    但是,如果您使用双链表,那么根据定义,您可以双向访问元素。从头到尾,从尾到头,因为使用的Node类中有双指针。因此,甚至不需要反向而是在需要时从尾部迭代到头部。

    【讨论】:

    • 您也不需要反转数组,您只需编写一个包装类来反向索引数组(根据this answer)。
    • @Dukeling 是的,但是,算法复杂度仍然是 O(n)。另一方面,当使用双链表时,您不必执行该步骤。因此,复杂度仅为 O(1)。您只需直接从尾部到头部访问元素。
    • 不,您可以将数组分配给包装类的成员(或者它可以从包装类开始)并简单地在包装类中设置一个“反转”标志(指示访问器和他们应该反向索引数组的mutators),都在O(1)中。
    • 我的意思是this
    • @Dukeling 因此,当它被标记为反转时,以另一种方式访问​​数组。在给出的示例中,确实复杂度为 O(1)。感谢您的规范。
    【解决方案5】:

    递归与迭代。函数调用(递归)成本周期。因此,对于这个解决方案,我会采用迭代方法。其他需要注意的事项是:偶数/奇数大小的数组、空数组、只有 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;
      }
    }
    

    这会存储一些值,以便真正避免重复(即额外的循环)。它还检查不需要反转的数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-24
      • 2011-04-13
      • 2012-09-22
      • 2018-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多