以递归方式反转长度为2 ^ n的整数数组,并返回一个新数组而不修改原始数组

时间:2014-09-18 02:19:29

标签: c arrays pointers recursion

我在采访中遇到了以下问题。

完成此功能以返回反转数组而不修改函数签名或原始数组。请注意,此处不应使用静态数据类型。

假设arrayLength是2的幂,即2 ^ n。 - >我认为这就是诀窍。

int* reverse(int *array, int arrayLength){

}

请帮忙。 请注意,我无法真正想到问题的解决方案。面试官暗示使用2 ^ n进行推理,但我无法真正想到解决方案。

8 个答案:

答案 0 :(得分:3)

这个怎么样:

int* reverse(int *array, int arrayLength){
  if (arrayLength==1) {
    int* out=(int*)malloc(sizeof(int));
    out[0] = array[0];
    return out;
  }
  int* left = reverse(array+arrayLength/2, arrayLength-arrayLength/2);
  int* right = reverse(array,arrayLength/2);
  int* out = (int*)realloc(left, sizeof(int)*arrayLength);
  memcpy(out+arrayLength/2, right, sizeof(int)*(arrayLength/2));
  free(right);
  return out;
}

答案 1 :(得分:2)

int* reverse(int *array, int arrayLength){
    if(arrayLength == 0) return array;
    int* ret = (int*)malloc(arrayLength*sizeof(int));
    for(int i=0;i<arrayLength;i++) ret[i] = array[arrayLength-1-i];
    return reverse(ret, 0); // technically recursive
}

答案 2 :(得分:2)

同意OP,提示是&#34; 2 ^ n&#34;。与许多递归函数一样:分而治之。

这个例程首先处理错误的参数和简单的长度。接下来,将长度分成两半并将其反转。通过连接反转的左和右子阵列来形成结果。首先,对,然后离开。

通常的清理

#include <string.h>
#include <stdlib.h>


int* reverse(int *array, int arrayLength) {
  // Check parameters
  if (array == NULL || arrayLength < 0) {
    ; // TBD HandleBadParameters();
  }

  // Allocate space for result, not much to do if length <= 1
  int *y = malloc(arrayLength * sizeof *y);
  if (y == NULL) {
    ; // TBD HandleOOM();
  }
  if (arrayLength <= 1) {
    memcpy(y, array, arrayLength * sizeof *y);
    return y;
  }

  // Find reverse of the two halves
  int halflength = arrayLength / 2;
  int *left = reverse(array, halflength);
  int *right = reverse(&array[halflength], halflength);

  // Append them to the result - in reverse order
  memcpy(y, right, halflength * sizeof *y);
  memcpy(&y[halflength], left, halflength * sizeof *y);

  // Clean-up and return
  free(right);
  free(left);
  return y;
}

答案 3 :(得分:1)

这是(并且有效):

int *reverse(int *array, int arrayLength)
{
    if (arrayLength > 1) {
        int i, n = arrayLength >> 1;
        int *m = calloc(n, sizeof(int));

        memcpy(m, array, n*sizeof(int));
        memcpy(array, array + n, n*sizeof(int));
        memcpy(array + n, m, n*sizeof(int));
        free(m);
        reverse(array, n); 
        reverse(array+n, n); 
    } /* for */
    return array;
} /* reverse */

它可以在没有临时存储的情况下完成,但你必须迭代一点。

int *reverse(int *a, int al) 
{
    if (al > 1) {
        int i, a1 = al >> 1;

        for (i = 0; i < a1; i++) {
            int temp = a[i];
            a[i] = a[i + a1];
            a[i + a1] = temp;
        } /* for */
        reverse(a, a1);
        reverse(a+a1, a1);
    } /* for */
    return a;
} /* reverse */

但是,从边界到中间进行交换并完全迭代会更好。

int *reverse(int *array, int arrayLength)
{
    int a, b;
    for (a = 0, b = arrayLength-1; a < b; a++, b--) {
        int temp = array[a];
        array[a] = array[b];
        array[b] = temp;
    } /* for */
    return array;
} /* reverse */

对于那些要求非自修改阵列的人来说,这种效率非常低效:

int *reverse(int *array, int arrayLength)
{
    int *a1, *a2;
    int *res;

    if (arrayLength > 1) {
        int l = arrayLength >> 1;
        a1 = reverse(array, l);
        a2 = reverse(array + l, l);
        res = calloc(arrayLength, sizeof(int));
        memcpy(res, a2, l*sizeof(int));
        memcpy(res+l, a1, l*sizeof(int));
        free(a1);
        free(a2);
    } else {
        /* we return always memory alloc'd with malloc() so we have to do this. */
        res = malloc(sizeof(int));
        *res = array[0];
    } /* if */

    return res;

} /* reverse */

答案 4 :(得分:0)

嗯,这是一种偷偷摸摸的方式,它并不关心阵列的长度。注意:我假设您无法引入新功能,必须在现有功能中完成所有功能

如果长度是正定的,它会分配内存并复制,然后再次使用负长度和副本调用reverse,然后如果函数以负长度调用,则会反转第一个和最后一个,然后递归通过移动到数组中的下一个调用并缩小长度,直到没有任何东西可以反转,然后递归函数展开

int* reverse(int *array, int arrayLength){
        int* result;
        if(arrayLength > 0)
        {
            result =(int*) malloc((sizeof(int)*arrayLength));
            memcpy(result, array, sizeof(int)*arrayLength);
            reverse(result, -arrayLength);
            return result;
        }
        else if(arrayLength < -1)
        {
            int end = (-arrayLength)-1;
            int temp = array[end];
            array[end] = array[0];
            array[0] = temp;
            return reverse(array+1, arrayLength+2);
        }   
        return array;
    }

答案 5 :(得分:0)

考虑到arrayLength始终是2的幂。我们将函数应用于数组的两个部分,然后以相反的方式连接它们。 最后,如果数组只有一个元素,我们只返回具有相同元素的其他数组。

int* reverse(int *array, int arrayLength){
    int * newArray = NULL;
    if(arrayLength == 1){
        newArray = (int *)malloc(sizeof(int));
        *newArray = array[0];
    } else if(arrayLength == 2){
        newArray = (int *)malloc(2 * sizeof(int));
        newArray[0] = array[1];
        newArray[1] = array[0];
    } else {
        // apply to first half
        int * first = reverse(array, arrayLength / 2);
        // apply to second half
        int * second = reverse(array + arrayLength / 2, arrayLength / 2);
        // allocate space
        newArray = (int *) malloc(arrayLength * sizeof(int));
        // copy parts in reverse way
        memcpy(newArray, second, arrayLength / 2 * sizeof(int));
        memcpy(newArray + arrayLength / 2, first, arrayLength / 2 * sizeof(int));
        // free allocated space for parts
        free(first);
        free(second);
    }
    return newArray;
}

答案 6 :(得分:0)

我会试一试。

知道阵列长度为2 ^ n意味着它可以安全地减半。我们在每一半上递归调用函数,直到长度为2.此时我们交换两个整数。想想{ 2,1,4,3,6,5,8,7 }。当我们从那里回来时,每一半都会被合并到它来自的地方({ 4,3,2,1,8,7,6,5})。冲洗并重复。

#include <stdio.h>
#include <stdlib.h>

int * reverse( int* arr, int length )
{

  if ( length == 1 )
  {
    int *result = malloc( sizeof( arr[0] ) );
    result[0] = arr[0];
    return result;
  }

  int * result = 0;

  if ( length == 2 )
  {
    result = malloc( sizeof( arr[0] ) * 2 );
    result[0] = arr[1];
    result[1] = arr[0];
  }
  else
  {
    int half_length = length / 2;

    // named correctly
    int * right = reverse( arr, half_length );
    int * left  = reverse( arr + half_length, half_length );

    result = malloc( sizeof( arr[0] ) * length );

    for ( int i = 0; i < half_length; ++i )
    {
      result[i] = left[i];
      result[ i + half_length ] = right[i];
    }

    free( right );
    free( left );
  }

  return result;

}

int main( void )
{
  int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  int length = 8;

  int *reversed = reverse( arr, length );

  for ( int i = 0; i < length; ++i )
  {
    printf( "%d %d\n", arr[i], reversed[i] );
  }

  free( reversed );
  return 0;
}

答案 7 :(得分:0)

对于具有2个以上元素的所有整数数组。 基本思路是从两端交换元素,直到剩余的元素数为1。

int * reverse_array(int * array,int arrayLength) {

if(arrayLength <2)
{
    return NULL;
}
else
{
     int *array1 = NULL;
     int *array2 = NULL;
     array1 = malloc(arrayLength*sizeof(int));
     memcpy(array1,array,arrayLength*sizeof(int));

     /*swap the start and end*/
     swap(array1,(array1+arrayLength-1));

      /* swap the next pair */
     array2 = reverse_array(array1+1,arrayLength-2);
     memcpy(array1+1,array2,(arrayLength-2)*sizeof(int));

     if(array2!= NULL)
     {
        free(array2);
     }
     return array1;
}

}