算法习题54:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分

本文介绍了如何将一个整数数组调整,使得所有奇数位于数组的前半部分,所有偶数位于后半部分。通过采用类似快速排序的思路,使用两个指针从两端遍历,达到O(n)的时间复杂度。文章还讨论了面试中可能遇到的扩展问题,如根据题目变化调整判断条件,并提出了解耦合的编程策略,引入了Java中的策略模式,以提高代码的灵活性和可扩展性。


调整数组顺序使奇数位偶数前面。
题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,
所有偶数位于数组的后半部分。要求时间复杂度为O(n)。

----------------------------------------------------------------

这道题难度不是很大,同样利用两个指针分别从头尾开始遍历到中间相遇即可。

其实这题就是快速排序的基本思想。

//============================================================================
// Name        : OddEvenRange.cpp
// Author      : YLF
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <malloc.h>
using namespace std;

void Range(int *arr, int n);
void Swap(int *arr, int i, int j);

int main() {

	int n = 0;
	cin>>n;
	int *arr = (int*)malloc(n*sizeof(int));

	int i = 0;
	for(i=0;i<n;i++)
		cin>>arr[i];
	Range(arr,n);
	for(i=0;i<n;i++)
		cout<<arr[i]<<" ";
	free(arr);
	return 0;
}

void Range(int *arr, int n){
	int i = 0, j = n-1;
	while(i<j){
		while(i<j&&arr[i] & 0x1)
			i++;
		while(i<j&&!(arr[j] & 0x1))
			j--;
		if(i<j)
			Swap(arr,i++,j++);
	}
}

void Swap(int *arr, int i, int j){
	int temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}

代码参见上面。

但是还没有结束,我上网搜了下这道题的相关答案,看到有一篇文章写得很好。

如果扩展面试官给我们的题目?


下面引自:http://www.shangxueba.com/ask/1192651.html

◆考虑可扩展性的解法,能秒杀Offer
如果是面试应届毕业生或者工作时间不长的程序员,面试官会满意前面的代码。但如果应聘者申请的是资深的开发职位,那面试官可能会接着 问几个问题。
面试官:如果把题目改成把数组中的数按照大小分为两部分,所有负数都在非负数的前面,该怎么做?
应聘者:这很简单,可以重新定义一个函数。在新的函数里,只要修改第二个和第三个while循环中的判断条件就行了。
面试官:如果再把题目改改,变成把数组中的数分为两部分,能被3整除的数都在不能被3整除的数的前面。怎么办?
应聘者:我们还是可以定义一个新的函数。在这个函数中……
面试官:(打断应聘者的话)难道就没有更好的办法?
这个时候应聘者应该要反应过来,面试官期待我们提供的不仅仅是解决一个问题的办法,而是解决一系列同类型问题的通用办法。这就是面试官在考查我们对扩展性的理解,即希望我们能够给出一个模式,在这个模式下能够很方便地把已有的解决方案扩展到同类型的问题上去。
回到面试官新提出的两个问题上来。我们发现要解决这两个新的问题,其实只需要修改函数ReorderOddEven中的两处判断的标准,而大的逻辑框架完全不需要改动。因此我们可以把这个逻辑框架抽象出来,而把判断的标准变成一个函数指针,也就是用一个单独的函数来判断数字是不是符合标准。这样我们就把整个函数解耦成两部分:一是判断数字应该在数组前半部分还是后半部分的标准,二是拆分数组的操作。于是我们可以写出下面的代码:

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

        if (pBegin<p End)
        {
            int temp=*p Begin;
            *pBegin=*p End;
            *p End=temp;
        }
    }
}
boo1 isEven (int n)
}
    return  (n&1)  = =0;
}


---------------------------------------------------------------------------------------------------------------------------------------------------------------------


看完上面这段引述,我想到的是Java里的策略模式

例如comparator这个比较器,我们只需要实现comparable这个接口,同时实现compareTo()这个方法即可得到比较结果,这种灵活度可以降低程序代码块之间的耦合度

http://blog.csdn.net/ylf13/article/details/12565423可以参见这篇对策略模式的编写
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值