重排数组元素使得所有的奇数位于所有偶数之前

来源:互联网 发布:苏州市信鸽网络 编辑:程序博客网 时间:2024/05/21 17:57
【题  目】输入一个整型的数组,调整数组的数字,使得所有的奇数位于数组的前半部分,所有的偶数都位于数组的后半部分。要求时间复杂度为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 }
复制代码

  运行结果如下:

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