今天有人向我询问了一个问题,我不相信这是可能的,但我可能是错的,或者我在想它。如何在不使用C语言迭代的情况下反转数组?
我的想法是,这是不可能的,因为数组可以是任何大小,并且在不使用某种形式的迭代的情况下,没有C程序可以用这种支持来表达。
答案 0 :(得分:23)
正如人们在评论中所说,这取决于迭代的定义。
如果将递归(简单地)作为替代进行迭代,那么Kalai提出的递归解决方案就是正确答案。
如果将迭代视为“检查每个元素”,那么问题就变成了阵列反转是需要线性时间还是可以在次线性时间内完成。
为了表明没有用于阵列反转的次线性算法,请考虑使用 n 元素的数组。假设存在用于反转的算法 A ,其不需要读取每个元素。然后,a[i]
中的某些i
存在元素0..n-1
,该算法永远不会读取,但仍然能够正确地反转数组。 (编辑:我们必须排除奇数长度数组的中间元素 - 请参阅下面的注释 - 请参阅下面的注释 - 但这不会影响算法是线性的还是渐近情况下的次线性。)
由于算法永远不会读取元素a[i]
,我们可以更改其值。说我们这样做。然后,从未读过这个值的算法将产生与我们改变其值之前相同的逆转答案。但是这个答案对于a[i]
的新值是不正确的。因此,不存在至少读取每个输入数组元素(保存一个)的正确反转算法。因此,数组反转具有O(n)的下限,因此需要迭代(根据此方案的工作定义)。
(请注意,此证明仅适用于阵列反转,不会扩展到真正具有次线性实现的算法,如二进制搜索和元素查找。)
如果迭代被视为“循环直到满足条件”,则转换为具有条件跳转的机器代码,已知需要一些严格的编译器优化(利用分支预测等)。在这种情况下,有人询问是否有一种方法可以做一些事情“没有迭代”可能会记住循环展开(到直线代码)。在这种情况下,您原则上可以编写直线(无环路)C代码。但这种技术并不普遍;只有事先知道数组的大小才有效。 (很抱歉将这个或多或少的轻率案例添加到答案中,但我这样做是为了完整性,因为我听说过以这种方式使用的术语“迭代”,并且循环展开是一个重要的编译器优化。)
答案 1 :(得分:14)
使用递归功能。
void reverse(int a[],int start,int end)
{
int temp;
temp = a[start];
a[start] = a[end];
a[end] = temp;
if(start==end ||start==end-1)
return;
reverse(a, start+1, end-1);
}
只需将上述方法称为 reverse(array,0,lengthofarray-1)
答案 2 :(得分:1)
实现递归函数以反转已排序的数组。即,给出阵列[1,2,3,4,5]你的 程序应该返回[5,4,3,2,1]。
答案 3 :(得分:0)
这是一个在javascript函数中使用递归的简洁解决方案。它不需要除数组本身之外的任何参数。
/* Use recursion to reverse an array */
function reverse(a){
if(a.length==undefined || a.length<2){
return a;
}
b=[];
b.push(reverse(copyChop(a)));
b.push(a[0]);
return b;
/* Return a copy of an array minus the first element */
function copyChop(a){
b=a.slice(1);
return b;
}
}
如下所示:
reverse([1,2,3,4]);
请注意,如果您不使用嵌套函数copyChop进行数组切片,则最终会将数组作为最终结果中的第一个元素。不太清楚为什么会这样呢
答案 4 :(得分:0)
#include<stdio.h>
void rev(int *a,int i,int n)
{
if(i<n/2)
{
int temp = a[i];
a[i]=a[n-i-1];
a[n-i-1]=temp;
rev(a,++i,n);
}
}
int main()
{
int array[] = {3,2,4,5,6,7,8};
int len = (sizeof(array)/sizeof(int));
rev(array,0,len);
for(int i=0;i<len;i++)
{
printf("\n array[%d]->%d",i,array[i]);
}
}