一. 问题
给定一个数组 A,描述一个将 A 逆转的高效算法。例如,如果 A = (1, 2, 3, 4, 5),逆转以后是 A = (5, 4, 3, 2, 1)。除了 A 本身使用的空间外,只能使用 O( 1 )的额外内存。算法的运行时间是多少?
二. 思路
规定只能使用固定大小的额外内存,说明需要用到元素交换,这将会改变原序列。(如果可以使用更多的内存,那么可以重新申请一个和原序列大小相同的新序列,然后将原序列元素从后往前,依次放入新序列中)。
三. 代码实现
1 void reverse_array(vector<int>& data) { 2 int temp; 3 for (int i = 0, j = data.size() - 1; i < j; ++i, --j) { 4 temp = data[i]; 5 data[i] = data[j]; 6 data[j] = temp; 7 } 8 }
算法正确性证明:
用到两个变量 i 和 j ,i 赋值为序列开始下标,j 赋值为序列结束下标。
现在需要分两种情况:
(1)当序列元素为偶数时,i 和 j 会在若干步以后,前后紧挨着,在执行完这一步以后, i 的值会大于 j ,说明序列元素全部逆转。
(2)当序列元素为奇数时, i 和 j 会在若干步以后相遇(都指向最中间的元素),而这个中间元素不需要与别人交换,或者说,它跟它自己进行交换,交换完成后,还是会出现 i 大于 j 的情况,说明整个序列逆转完成。显然,自己和自己交换这一步骤是多余的。
于是我们可以证明,该算法正确,并且时间复杂度是 O(n),因为遍历一遍序列即可完成任务。