面试题14:调整数组顺序是奇数位于偶数前面

44 篇文章 0 订阅
<pre name="code" class="cpp">/*面试题14
  题目:输入一个整数数组,实现一个函数来调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
  简单的思路是:扫描数组,碰到一个偶数,拿出来,把数组后面的数字向前移动,数组末尾出现一个空位,把这个偶数放入空位。每碰到一个偶数需要移动O(n)个数字,因而总的时间复杂度是O(n*n)。
  思路二:可以维护两个指针,一个指向数组的第一个,向后移动;一个指向数组的末尾,向前移动。两个指针相遇之前,如果第一个指向的是偶数,并且第二个指向的是奇数,就交换这两个数字。
void RecorderOddEven(int *pData,unsigned int length)
{
	if(pData==NULL||length=0)
		return;
	int *pBegin=pData;
	int *pEnd=pData+length-1;
	while(pBegin<pEnd)
	{
		//向后移动pBegin,直到指向偶数
		while(pBegin<pEnd&&(*pBegin&0x1==1))
			pBegin++;
		//向后移动pEnd,直到指向奇数			
		while(pBegin<pEnd&&(*pEnd&0x1==0))
			pEnd++;
		//pBegin直到指向偶数,pEnd直到指向奇数,交换两个数字
		if(pBegin<pEnd)
		{
			int temp=*pBegin;
			*pBegin=*pEnd;
			*pEnd=temp;
		}
	}
}
如果题目改成数组分为两部分,负数在正数前面或者能被3整除的数在不能被3整除的数前面,考察的是对扩展性的理解,给出一个模式,这个模式可以很容易的用到同类型问题上去。
我们发现解决新问题需要改动的是函数中的两处判断的标准,大的逻辑框架不需要改动。这样把整个函数解耦成两部分:一个判断数字是在数组的前半部分还是后半部分二是拆分操作。
*/
void Reorder(int *pData,unsigned int length,bool (*func)(int))
{
	if(pData==NULL||length==0)
		return;
	int *pBegin=pData;
	int *pEnd=pData+length-1;
	while(pBegin<pEnd)
	{
		//向后移动pBegin,直到指向偶数
		while(pBegin<pEnd&&!func(*pBegin))
			pBegin++;
		//向后移动pEnd,直到指向奇数			
		while(pBegin<pEnd&&func(*pEnd))
			pEnd--;
		//pBegin直到指向偶数,pEnd直到指向奇数,交换两个数字
		if(pBegin<pEnd)
		{
			int temp=*pBegin;
			*pBegin=*pEnd;
			*pEnd=temp;
		}
	}
}
bool isEven(int n)
{
	return (n&0x1)==0;
}
void ReorderOddEven(int *pData,unsigned int length)
{
	Reorder(pData,length,isEven);
}
//测试用例包括:功能测试(数组中奇数、偶数交替出现;奇数都在偶数前面;偶数都在奇数前面),特殊输入测试(输入NULL指针,数组只有一个数字)。


 

 
</pre><pre name="code" class="cpp">java代码实现

<pre name="code" class="java">package com.array;

public class AdjustOrder {  
    public static void main(String[] args){  
        int[] arr = {2,2,6,5,3,8,9,3,6,5,7};  
        Reorder(arr);  
        for(int i=0;i<arr.length;i++){  
            System.out.print(arr[i]+",");  
        }  
    }  
    public static boolean isEven(int n ){  
        return (n&0x1)==0;  
    }  
    public static void Reorder(int[] arr){  
        if(arr == null){  
            return ;  
        }  
        int small = 0;  
        int big = arr.length-1;  
        while(small<=big){  
            if(!isEven(arr[small]))small++;  
            if(isEven(arr[big])) big--;  
            if(isEven(arr[small])&&!isEven(arr[big])){  
                int temp = arr[small];  
                arr[small] = arr[big];  
                arr[big] = temp;  
            }  
        }  
    }   
} 


 
 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值