剑指offer面试题21——调整数组顺序使奇数位于偶数前面

题目:

        输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分。

 

思路1:

         这道题可以联想到“Two Points”的经典解题思路,就是建立两个指针分别指向数组的首末元素,第一个指针指的元素如果是奇数就把指针往后滑动,直到遇到一个偶数后停下来;第二个指针所指的元素如果是偶数就把指针向前移动,直到遇到一个奇数后停下来。这时候判断第一个指针是否在第二个指针的前面,如果是那么交换两个指针所指元素的值,如果不是,那么说明数组的调整结束。这样遍历一轮数组就可以完成对数组的调整。

代码:

void ReorderOddEven(int *pData, unsigned int length)
{
	if (pData == nullptr || length == 0)
		return;
	int *pBegin = pData;
	int *pEnd = pData + length + -1;
	while (pBegin<pEnd)
	{
		while (pBegin < pEnd && (*pBegin & 0x1) != 0)
		{
			//向后移动pEnd,直到它指向偶数
			pBegin++;
		}
		while (pBegin<pEnd && (*pEnd & 0x1)==0)
		{
			//向前移动pEnd,直到它指向奇数
			pEnd--;
		}
		if (pBegin < pEnd)
		{
			int temp = *pBegin;
			*pBegin = *pEnd;
			*pEnd = temp;
		}
	}
}

 

 思路2:

         这道题还可以扩展一下,比如将所有的负数调整到前面,正数调整到后面,或者将能整除3的数放到前面,其余的数放到后面。其实,交换的方法是不变的,变的的判断的条件。那么,为了提高函数的可扩展性,我们可以将调整和条件判断分成两个函数,这样当题目的调整内容发生改变时,只需要改变条件判断函数里面的内容就好了。这种做法可以很大地提高函数的可扩展性,面试的时候会让面试官更加满意。里面判断奇数还是偶数的方法(a&0x1)要学着用啊。

注意:

这里面涉及到一个知识点,就是函数指针作为函数参数传递。函数A作为参数传递给函数B时,函数B声明如下:

int A(int a,int b);

B(arg_list,int (*pA)(int, int));

函数B调用如下:

B(...,A);

代码:

void Reorder(int* pData, unsigned int length, bool(*func)(int))
{
	if (pData == nullptr || length == 0)
		return;
	int*pBegin = pData;
	int*pEnd = pData + length - 1;
	while (pBegin<pEnd)
	{
		while (pBegin < pEnd && !func(*pBegin))
			pBegin++;
		while (pBegin < pEnd && func(*pEnd))
			pEnd--;
		if (pBegin < pEnd)
		{
			int temp = *pBegin;
			*pBegin = *pEnd;
			*pEnd = temp;
		}
	}
}

bool isEven(int n)
{
	return(n & 1) == 0;
}

void ReorderOddEven(int* pData, unsigned int length)
{
	Reorder(pData, length, isEven);
}

复习:

   前面的思路比较简单,还是要好好注意这种扩展性怎么来实现,即函数指针作为另外一个函数的参数。

二刷代码:

void Reorder(int* pData, unsigned int length,bool (*func)(int))
{
	if (pData == nullptr || length == 0)
		return;
	int* pStart = pData;
	int* pEnd = pData + length - 1;
	while (pStart>pEnd)
	{
		while (!func(*pStart)&& pStart<pEnd)
		{
			pStart++;
		}

		while (func(*pEnd) ==0&&pStart<pEnd)
		{
			pEnd++;
		}
		if (pStart < pEnd)
		{
			int temp = *pStart;
			*pStart = *pEnd;
			*pEnd = temp;
		}

	}
}

bool isEven(int n)
{
	return (n & 1) == 0;
}

void ReorderOddEven(int *pData, unsigned int length)
{
	Reorder(pData, length, isEven);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值