问题:仅用O(1)的空间,将整数数组按奇偶数分成2部分,数组左边是奇数、右边是偶数。请给出完整代码,尽量高效,简洁。
这是我在牛客网看见的一道题,得到问题以后先分析题目要求,第一个要求就是用O(1)的空间解决问题,所谓O(1)空间复杂度即无论要操作的数组多长,使用的空间资源都是一定 的且有限 的(说人话就是:不管你搞多长的数组,我就用这几个变量就给你把这事弄了),举一个不是O(1)的反例就是,我做这个题大不了在定义两个数组(也可以只再定义一个,反正一个数不是奇数就是偶数,加上本来那个数组,两个数组就够分类了),然后一个一个的去看原数组元素,然后把数一个一个提溜出来,分类放好后再把他们合并得到想要的的结果,这中方法很好去理解,但是他的空间是O(n),如果是一个长度为10,100的数组还好说,如果数组长度是1K,10K或者更多,我们要考虑到最坏的情况也要定义等长的数组来解决问题,显然这是十分不可取的。
我之前学习过快速排序,收到快速排序算法思想的启发,我对这一题的解题思路是这样是:
定义两个整型变量来记录数组两头的坐标,一个从头向尾跑只盯着偶数看,一个从尾向头跑只盯着奇数看,如果某个坐标盯下的数组元素就是自己盯着的类型则视为逮住了,一个坐标如果先逮到自己盯的类型的数,则先停下来等等另一个坐标,当两个坐标都逮住了自己盯到的数,然后将两个数组元素交换,然后两个坐标继续按着自己的方向跑,直到两坐标遇到了。
如果这样说比较抽象那我就打个比方:
计科和软工要站一队,队也确实站好了,但是计科和软工交错相站,有说有笑,导员看了不高兴了,要求软工站一边计科一边,这时两个班班长站出来,一个从队头看,一个从队尾看,专门就看有没有不是自己班的人,如果两个班长都找到不是自己班的人了就让这两个人互换位置,然后继续找下一对,直到这两个班长碰面了,软工班长说:“我这边没你们计科的人了”,计科班长也说:“我这边也没有你们软工的人了”,此时这个队就算是排好了。
具体实现代码如下(Java):
import java.util.Scanner;
public class Test0412
{
public static void main(String[] args)
{
int[] arr=new int[10];//以长度为10为例
Scanner sc =new Scanner(System.in);
for(int i=0;i<arr.length;i++) arr[i]=sc.nextInt();//输入长度为10 的整型数组
int a=0,b=arr.length-1,temp;
while(true)
{
if(a>=b) break;
if((arr[a]%2==0)&&(arr[b]%2==1))
{
temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
a++;
b--;
}
if(arr[a]%2==1) a++;
if(arr[b]%2==0) b--;
}
for(int i=0;i<arr.length;i++) System.out.print (arr[i]+" ");
System.out.println();
}
}
测试运行结果如下:
PS:该程序是按思路编写,并自行测试运行,并没用通过OJ系统验证其正确性,若有错误请指出,我将虚心改正!