【算法18】重排数组元素使得所有的奇数位于所有偶数之前

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

  【思 路1】首先我们不考虑时间复杂度的要求,直观考虑:我们只需要从头到尾扫描整个数组,如果碰到奇数,放到第一的位置;如果碰到偶数,就放到最后的位置。这样就OK了。然后我们来分析这种算法的效率问题:首先我们需要一个临时变量来保存需要移动的元素,因而空间复杂度为O(1).时间上,对于第i个元素,它是奇数和偶数的概率各为1/2,因而它有1/2的概率向前移动(i-1)个位置,有1/2的概率想后移动(n-i)个位置,因而平均下来要移动(n-1)/2的位置,也就是说对于任意一个元素平均要移动(n-1)/2个其他元素,因而所有元素要移动的次数就是n(n-1)/2,所以这种算法的时间复杂度为O(n)。

  【思 路2】这道题只是要求奇数排在偶数的前面,因而我们完全没有必要一个元素一个元素的进行分析,我们可以考虑每次分析一对元素,首尾指针?yes!我们在定义两个指针,分别指向数组的第一个元素和最后一个元素,然后进行判断,如果第一个元素为偶数,第二个元素为奇数,那么我们就交换,否则,我们直接移动指针指向下一个(上一个)元素即可。当两个指针相遇的时候就完成遍历了。这样我们的时间复杂度就为O(n)。根据这种思路,我们可以很容易的写出如下的代码:

 1 #include<iostream>
2 #include<string>
3 using namespace std;
4
5 //重排数组使得所有奇数位于数组的前半部分
6 //所有的偶数位于数组的后半部分
7 void ReorderOddEven(int numbers[],int length)
8 {
9 if(numbers == NULL || length <= 0)
10 return;
11
12 //首尾指针,两头往中间遍历
13 int *start = &numbers[0];
14 int *end = &numbers[length-1];
15
16 while(start < end)
17 {
18 //首指针指向奇数,指针后移
19 if(*start % 2 == 1)
20 {
21 start++;
22 continue;
23 }
24
25 //尾指针指向偶数,指针前移
26 if(*end % 2 == 0)
27 {
28 end--;
29 continue;
30 }
31
32 //首指针指向指向偶数,同时尾指针指向奇数,交换;
33 int temp = *start;
34 *start = *end;
35 *end = temp;
36 }
37
38 }
39
40 int main()
41 {
42 cout<<"Enter your arrayLength:"<<endl;
43 int n = 0;
44 cin>>n;
45
46 cout<<"Enter your array elements:"<<endl;
47 int *array = new int[n];
48 for(int i = 0;i < n;++i)
49 {
50 cin>>array[i];
51 }
52
53 cout<<"the orginal array is:"<<endl;
54 for(i = 0;i < n;++i)
55 {
56 cout<<array[i]<<" ";
57 }
58 cout<<endl;
59
60 ReorderOddEven(array,n);
61
62 cout<<"the resorted array is:"<<endl;
63 for(i = 0;i < n;++i)
64 {
65 cout<<array[i]<<" ";
66 }
67 cout<<endl;
68
69 return 0;
70 }

  运行结果如下:

  反思:这道题很简单,基本上稍作思考,就能写出如上的代码,然而仍然有很多小细节没有注意到,何海涛博主的考虑得就比较的全面,这个代码的重用性很差,如果换成所有的负数排在所有的正数的前面,我们就要重新修改函数中的部分代码,他在博客中将该函数分离开来,做到了重排数组的算法和重排标准的分离,这样只要修改重排标准,就可以轻易的实现代码的重用。看来我水平还是差很多,继续努力!


 

 

References:

程序员面试题精选100题:http://zhedahht.blog.163.com/blog/static/25411174200741295930898/

注:

1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。


posted @ 2011-12-11 21:09  python27  阅读(1765)  评论(0编辑  收藏  举报