剑指offer——面试题14:调整数组顺序是奇数位于偶数前面

    题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

   1、 我的解法代码:

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        //if(array == NULL)
            //return ;
        for(decltype(array.size()) i = 0;i < array.size();++i)  // 每一个数都要遍历,所以是 size()次
        {
            for(decltype(array.size())j = array.size()-1 ;j>i;j--)
            {
                if ((array[j] %2 ==1) &&(array[j-1] %2 == 0))
                    swap(array[j],array[j-1]);
            }
        }
    }
};

    分析:比如数字1 2 3 4 5 6 7 8,要先遍历一下,然后调整数字的顺序。遍历的话,肯定要循环 array.size()次。如果要调换顺序的话,得从后往前调整,因为偶数需要不停地往后调整。我这种解法代码简洁,但是时间复杂度很高,为 O(n^2).但是好处是不需要额外的辅助空间。

    2、《剑指offer》上的解法 P105页

    剑指offer一书上,特别强调了程序的可扩展性。参考书吧。但是大体上和我的解法差不多,有两点不同:

    (1)、判断奇偶数,是将该数和 0x1进行“与”运算,这样,利用位运算,确实比取余效率要高。

    (2)、书上使用的是指针的解法,因为形参给的就是指针。而牛客网上这道编程题的形参是 vector 的引用


    3、时间复杂度O(n),空间复杂度为O(n)的解法

    思路:可以额外申请一个数组,把原来数组里面的元素遍历一遍,如果是奇数,就放到数组中。再把原来的数组遍历一遍,如果是偶数就放到数组中。时间复杂度为O(n),而且还不用排序的思想。

    代码:

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        vector<int> result;
        for(decltype(array.size())i = 0;i < array.size();++i)
            if(array[i]%2 == 1)
                result.push_back(array[i]);
        for(decltype(array.size())i = 0;i < array.size();++i)
            if(array[i] %2 == 0)
                result.push_back(array[i]);
        array = result;
        
    }
};

    4、利用c++ 中 STL 中的 stable_partition()函数

    这个函数的功能是,如果isOK是真的,放到数组的前面,如果是假的,放到数组的后面。

    代码:

bool isOK(int n)
    {
        return ((n & 1) == 1);
    }
class Solution {
public:
    
    void reOrderArray(vector<int> &array) {
        stable_partition(array.begin(),array.end(),isOK);
    }
};

    其中,源码为:

template <class BidirectionalIterator, class UnaryPredicate>  
  BidirectionalIterator partition (BidirectionalIterator first,  
                                   BidirectionalIterator last, UnaryPredicate pred)  
{  
  while (first!=last) {  
    while (pred(*first)) {  
      ++first;  
      if (first==last) return first;  
    }  
    do {  
      --last;  
      if (first==last) return first;  
    } while (!pred(*last));  
    swap (*first,*last);  
    ++first;  
  }  
  return first;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值