面试题14:调整数组顺序使奇数在偶数前面

来源:互联网 发布:花生壳域名忘记了 编辑:程序博客网 时间:2024/06/01 19:25

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


     咋一看,没有限定空间复杂度,直接想到声明两个数组,一个存奇数,一个存偶数。再合并。时间复杂度O(n),空间复杂度O(n),代码如下:

      

class Solution {public:    void reOrderArray(vector<int> &array) {        vector<int> oddArray;        vector<int> evenArray;        int i;        for(i=0;i<array.size();i++)        {            if(array[i]%2==1)            {                oddArray.push_back(array[i]);            }            else                evenArray.push_back(array[i]);        }        for(i=0;i<oddArray.size();i++)        {            array[i]=oddArray[i];        }        for(i=0;i<evenArray.size();i++)        {            array[oddArray.size()+i]=evenArray[i];        }        return ;    }};
     面试时感觉这种肯定过不了。考虑下节省空间复杂度。

     再看一下题目,发现我一开始就跑偏了,我开始想的是数组以前元素的相对顺序不变,结果看本题好像没有这个意思,那就更简单了。

     采用两个指针,一个指向数组的开头,一个指向数组的结尾。当开头的指针遇到奇数,跳过,遇到偶数,停止,指向数组末尾的指针遇到偶数,跳过,遇到奇数,停止。然后两个指针交换元素。这种思想类似于快速排序中的partition思想。算法原地调整,时间复杂度O(n),空间复杂度O(1).

     先试着写个。

     

class Solution {public:    void reOrderArray(vector<int> &array) {        int i=0,j=array.size()-1;        while(i<=j)        {            while(i<array.size()&&array[i]%2==1) i++;            while(j>=0&&array[j]%2==0) j--;            if(i<=j)                swap(array[i],array[j]);        }        return;    }};
      不过快速排序本身就是不稳定的排序方法,这种方法虽然奇数在前,偶数在后,但是肯定数组的元素相对顺序和以前不同。如1,2,3,4,5肯定变成了1,5,3,4,2.

      看网上有人为了使算法具有稳定性,采用归并排序,可是归并排序要的空间复杂度就是O(n),有那个O(n)还不如直接像开始一样声明两个数组呢。

      想到腾讯今年的实习笔试,有一道类似的题目,但是是要求空间复杂度是O(1),那没办法,只有牺牲时间复杂度了。

      代码如下:

       

class Solution {public:    void reOrderArray(vector<int> &array) {        int len=array.size(),i,j,k,l;        for(i=len-1,j=len-1;i>=0&&j>=0;)          //i,j分别代表最前的一个偶数,奇数指针        {            if(array[i]%2==0)                     //当前为偶数,直接跳过            {                    i--;                j--;            }            else            {                for(k=j-1;k>=0;)                 //当前array[i]是奇数,寻找下一个偶数,再将偶数和后面所有的不是偶数的都交换                {                    if(array[k]%2==1)                        k--;                    else                    {                        int temp=array[k];                        memcpy((char *)(&array[k]),(char *)(&array[k+1]),sizeof(int)*(i-k));                        array[i]=temp;                        break;                       /* for(l=k;l<i;l++)                        {                            swap(array[l],array[l+1]);                        }                        break;*/                    }                }                i=i-1;                              //更新偶数指针                j=k;                                //更新奇数指针            }        }    }};
     本算法理论上时间复杂度O(n*n*n),但是实际肯定不到。思考用内存拷贝,会快点,理论时间复杂度为O(n*n).

0 0