Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.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 提高Alog的效率(将阵列向左旋转n次迭代)_Java_Arrays_Algorithm_Performance_Big O - Fatal编程技术网

Java 提高Alog的效率(将阵列向左旋转n次迭代)

Java 提高Alog的效率(将阵列向左旋转n次迭代),java,arrays,algorithm,performance,big-o,Java,Arrays,Algorithm,Performance,Big O,我正在解决将数组向左旋转n迭代次数的难题。 代码非常有效,但在非常巨大的输入上滞后。 如何进一步提高效率 // Complete the rotLeft function below. static int[] rotLeft(int[] a, int iterations) { for(int i=0;i<iterations;i++) { int[] temp=Arrays.copyOfRange(a, 1, a.length);

我正在解决将数组向左旋转
n
迭代次数的难题。 代码非常有效,但在非常巨大的输入上滞后。 如何进一步提高效率

// Complete the rotLeft function below.
static int[] rotLeft(int[] a, int iterations) {

      for(int i=0;i<iterations;i++)
      {
         int[] temp=Arrays.copyOfRange(a, 1, a.length);  
         temp=Arrays.copyOf(temp,a.length);
         temp[a.length-1]=a[0];
         a=temp;
      }


      return a;
}
//完成下面的rotLeft函数。
静态int[]旋转左(int[]a,int迭代){

对于(int i=0;i而不是移位
迭代
可以直接计算最终位置

finalIndex=(index-iterations+a.length)  % a.length
+a、 添加长度以确保
finalIndex
始终不是一个否定值

如果你把这个应用到你的算法中,你就可以摆脱循环,一步完成整个过程

这将算法的时间复杂度从O(a.length*iterations)降低到O(a.length)

那么:

    static int leftRotate(int arr[], int iterations, 
                                     int k) 
    { 
        /* To get the starting point of  
        rotated array */
        int mod = k % iterations; 

        // Prints the rotated array from  
        // start position 
        for(int i = 0; i < iterations; ++i) 
        System.out.print(arr[(i + mod) % iterations] 
                          + " ");  

        System.out.println(); 
    } 

leftRotate(arr, iterations, arr.length);
static int leftRotate(int arr[],int迭代,
int(k)
{ 
/*获得
旋转阵列*/
int mod=k%迭代次数;
//从中打印旋转的数组
//起始位置
对于(int i=0;i

Ref:

您不需要每次迭代都这样做。相反,您可以创建一个公式来计算每个元素的去向

例如,假设数组的大小为n

然后,如果需要将数组向左移动1次迭代,那么位置p处的元素将位于(p+1)%n的位置

对于i次迭代,每个元素都将位于(p+i)%n的位置。因此,不需要每次迭代都有一个循环

   static int[] rotLeft(int[] a, int iterations) {
        int[] answer = new int[a.length];
        for(int i=0;i<a.length;i++)
        {
            answer[i] = a[(i - iterations + a.length) % (a.length)];
        }
        return answer;
    }
static int[]rotlefit(int[]a,int迭代次数){
int[]答案=新的int[a.长度];

对于(int i=0;i,代码中几乎没有缺陷

  • 首先,进行冗余工作-如果
    iterations>a.length
    ,那么在a.length迭代之后,数组将返回自身
  • 其次,每次迭代都会创建一个全新的数组副本
  • 第三,数组中每个元素的新位置可以通过只查看数组长度、所需迭代次数和该元素的索引来预先确定,无需重复迭代
在考虑这些因素时,这可以归结为以下形式:

 static int[] rotLeftEfficient(int[] a, int iterations) {
    iterations = iterations % a.length;
    int[] b = new int[a.length];
    for (int i = 0; i < a.length; i++) {
        int newIndex = (i - iterations + a.length) % a.length;
        b[newIndex] = a[i];
    }
    return b;
}
static int[]rotleffective(int[]a,int迭代次数){
迭代次数=迭代次数%a.长度;
int[]b=新的int[a.长度];
for(int i=0;i
这归结为
O(n)
解决方案-其中
n
是数组中的元素数,也有适当的常数。

这里有一个旋转到位(不使用第二个数组),时间复杂度为O(a.length)。在我的系统(英特尔3770K 3.5ghz)上,它可以在.17中旋转2^28=268435456个元素数组(旋转76)到.85秒(旋转1)。交换按顺序访问顺序完成,这是缓存友好的

    // rotate in place
    public static void rolip(int[] a, int r){
        r = r % a.length;
        if(r == 0)
            return;
        int t;
        int n = a.length - r;
        int i = 0;
        int j;
        while(true){
            if(r <= n){                     // shift left r places
                for(j = i+r; i < j; i++){
                    t = a[i];               //  swap(a[i], a[i+r])
                    a[i] = a[i+r];
                    a[i+r] = t;
                }
                n -= r;
                if(n == 0)
                    break;
            } else {                        // shift right n places
                i += r;
                for(j = i+n; i < j; i++){
                    t = a[i];               //  swap(a[i], a[i-n])
                    a[i] = a[i-n];
                    a[i-n] = t;
                }
                i -= n+r;
                r -= n;
                if(r == 0)
                    break;
            }
        }
    }
//原地旋转
公共静态无效rolip(int[]a,int r){
r=r%a.长度;
如果(r==0)
返回;
int t;
int n=a.长度-r;
int i=0;
int j;
while(true){

if(r)反转整个数组(原地)。然后在
0
iterations-1
之间反转。然后在
iterations
a.length-1
之间反转(实际上这是右移,但想法相同).@josejuan我为什么要这样想呢?它不受任何地方的限制,作为面试官,这是一个边缘案例,我会接受面试者检查我是否在面试中使用这个问题。@josejuan我不遵循。这个解决方案适用于所有输入,即使没有先决条件,即
iterations>a.length
,成本很小(1个额外的modolus操作),我真的看不到使用它的缺点。我使用一个2^28=268435456元素数组测试了代码。分配b[]几乎花费了0.3秒,所以我在main()中这样做了并将b作为参数传递给rotate函数。通过此更改,rotate函数大约需要0.65秒,比我的答案的最坏情况(rotate 1)快0.85秒,比我的答案的最佳情况下的0.17秒慢。我不知道Java是否优化了%a.length以使用乘反法而不是除法。可以用if/减法序列替换%以加快速度。为一个0.3秒的大数组分配时间使其总体速度变慢。这并不能满足所有用例,但只有少数。@AliAkram哪个用例不能实现?这里的
index
是什么?有一个更有效的方法:)(但我现在没有时间了)@Ali Akram:
index
是元素开始的位置。@josejuan:比O(a.length)快?如果我们在所有元素都已更改的末尾需要一个数组,这可能是不可能的。@MrSmith42-不快于O(a.length),但恒定时间更快。如果以较大的迭代值旋转一个大数组,将有大量缓存未命中。我的回答显示一个就地(没有第二个数组)进行交换的解决方案,即更多的写入,但这些操作是按顺序进行的,不考虑迭代次数,这对缓存更友好。对于较低的
min(r,a.length-r)
值,性能非常差,惩罚与
1/min(r,a.length-r)
(因此,对于大于10~100的值,惩罚是不可接受的,但对于较低的值,惩罚是不可接受的)@josejuan-这种类型的就地合并通常用于就地(无第二个数组)合并排序,例如,“它必须非常小”30%不是很小(相同的
rolip
具有不同的
r
),事实上,如果使用中间 public static void rol(int[] a, int r){ r = r % a.length; if(r == 0) return; int n = a.length - r; int i; int j; if(r <= n){ // if left rotate int[] b = new int[r]; // save elements for(j = 0; j < r; j++) b[j] = a[j]; for(i = 0; i < n; i++) // shift elements a[i] = a[j++]; for(j = 0; j < r; j++) // copy saved elements a[i++] = b[j]; } else { // else right rotate int[] b = new int[n]; // save elements i = 0; for(j = r; j < a.length; j++) b[i++] = a[j]; i = j-1; // shift elements for(j = i-n; j >= 0; j--) a[i--] = a[j]; for(j = 0; j < n; j++) // copy saved elements a[j] = b[j]; } }