一、题目:
给出将整型数组a中数据元素实现就地逆置的算法。所谓就地逆置,就是利用数组a原有空间来存放数组a中逆序排放后的各个数据元素。
二、题目分析:
就是有一个整型的数组,将他的顺序进行倒置,且还是用原数组的地址空间进行存储,不可以改变他的数组的地址。
三、解决方法
算法追求的就是利用更小的空间更短的时间来解决问题。下面先说下很容易就可以想到的一种解决方案。
1.方式一
/** * 思路:使用一个数组做中间变量,存储倒叙的a数组 * @param a * @return */ public static int[] getReverseArray(int[] a){ int[] b = new int[a.length]; for(int i=0;i<a.length;i++){ b[b.length-1-i] = a[i]; } for(int i=0;i<a.length;i++){ a[i]=b[i]; } return a; }
2.方式二
上面的方案,会有一个中间数组,且需要两次的循环,这无疑在空间和时间上都不是一个优秀的解决方案,更不是一个好的算法。其实我们可以使用这种方式来解决。
/** * 思路:逆置,那就交换首尾的元素。 * @param a * @return */ public static int[] getReverseArrayTwo(int[] a){ int tem = 0; for(int i=0;i<a.length;i++){ if(i<a.length-1-i){ tem = a[i]; a[i] = a[a.length-1-i]; a[a.length-1-i]=tem; } } return a; }
这种方案,就是直接交换收尾的元素即可实现该功能,无需对中间数组,也无需多次循环,此外需要注意,我们需要控制交换的次数,很明显我们需要交换一半的次数就行,稍微分析便可以知道,中间值的下标最大也会小于a.length/2,所以使用该值控制交换的次数。此种方案,在时间和空间上无疑都是较优秀的一种。
3.方式三
方式二已经是一种较为优秀的解决方案了,但是他仍然不是一种最优的解决方案,因为在实现的过程中仍然可能会有多余的交换,而且方式二中的判断交换次数其实可以使用其他方案进行解决,如下代码才是比较完美的解决方案。
//方式三 /** * 思路:通过对方式二的修改得来,无需控制次数,知道数组的长度,知道起始下标,那么我们就可以 * 正续倒续一起查找,然后交换,这样当查找到同样的元素就代表已经交换完了。 * @param a * @return */ public static int[] getReverseArrayThree(int[] a){ int tem = 0; for(int i=0,j=a.length-1;i<j;i++,j--){ tem = a[i]; a[i] = a[j]; a[j] = tem; } return a; }
四、总结
这是笔者在看书时碰到的一个题目,前两种是笔者自己想出来的解决方案,最后一种则是参考了数上的思路写出来的。很明显书上给出的答案是最优的一种,这里总结并记录下。若是路过得你,有更好的解决方案,还希望不吝赐教。