zoukankan      html  css  js  c++  java
  • 【算法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/。对解题思路有任何建议,欢迎在评论中告知。


  • 相关阅读:
    戴尔服务器IDRAC命令配置IP地址
    python 生成excel,并下载到本地
    python api
    python发送邮件
    大型线上系统迁移为分布式系统案例
    2014程序员之路
    Java EnumSet工作原理初窥
    C# 引用访问权限
    分享一些我的入门经历
    分享一些我的阅读习惯
  • 原文地址:https://www.cnblogs.com/python27/p/2284185.html
Copyright © 2011-2022 走看看