【LeetCode & 剑指offer刷题】数组题13:21 调整数组顺序使奇数位于偶数前面

【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

21 调整数组顺序使奇数位于偶数前面

题目描述

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
 
/*
方法:用一个临时数组存奇数和偶数,联系问题odd even linked list
O(n), O(n)用空间换时间
*/
#include <algorithm>
class Solution
{
public:
    void reOrderArray(vector<int> &a)
    {
        if(a.empty()) return;
       
        vector<int> result;
        for(int i = 0; i<a.size(); i++)
        {
            if(a[i] % 2 == 1) result.push_back(a[i]);
        }
        for(int i = 0; i<a.size(); i++)
        {
            if(a[i] % 2 == 0) result.push_back(a[i]);
        }
        a = result;
    }
};
/*
无法保证调整后,奇数与奇数之间,偶数与偶数之间相对位置不变(可优化,用stable_partition,O(nlogn)
和partition函数比较像
O(n), O(1)
*/
void reOrderArray(vector<int> &a)
{
    if(a.empty()) return;
 
    int left = 0, right = a.size()-1;
    while(left < right) //从两边向中间扫描
    {
        //向右移动left指针,直到指向偶数
        while(left<right && a[left]%2 != 0) left++;//若为奇数时,向前移动
        //向左移动right,直到指向奇数
        while(left<right && a[right]%2 == 0) right--;
        //交换
        swap(a[left], a[right]);
    }
}
 
来源:牛客网
/**
 * 1.要想保证原有次序,则只能顺次移动或相邻交换。
 * 2.i从左向右遍历,找到第一个偶数。
 * 3.j从i+1开始向后找,直到找到第一个奇数。
 * 4.将[i,...,j-1]的元素整体后移一位,最后将找到的奇数放入i位置,然后i++。
 * 5.終止條件:j向後遍歷查找失敗。
 */
 
联系partition函数
//分割函数
//选择一枢轴分割序列,并返回其位置
int partition(vector<int>& a, int left, int right)
{
    //1. 初始化,用序列的第一个元素作为枢轴(也可用其他元素,但是要把枢轴元素暂时放到起始位置,方便后续交换,如三数中值初始化枢轴)
    //2. median3
    //3. srand((unsigned)time(NULL));  用随机法较简单
        // int pivotPos = rand() % (right - left) + left;   //得到随机基元的位置(下标)
        // swap(a[pivotPos], a[left]) //将枢轴暂时放入起始位置
    int pivot = left;           
    while (left < right)    //从序列的两端交替地向中间扫描(在此循环中a[pivot]不动,退出循环后在被交换)
    {
        //rightleft(因为left初始等于pivot),以使left最后指向等于枢轴位置元素或者小于枢轴位置的元素(这样最后a[pivot]与a[left]交换才不会出错?)
        while (left < right&&a[right] >= a[pivot]) right--;//找到本次扫描中第一个不满足枢轴规律的高位数
        while (left < right&&a[left] <= a[pivot]) left++;   //找到本次扫描中第一个不满足枢轴规律的低位数
        swap(a[left], a[right]);                        //交换以使满足枢轴规律
    }//最后结果是leftright均指向枢轴位置
    swap(a[left], a[pivot]);//将枢轴移动到位
    return left;            //返回枢轴位置
}
 
推广:
  • 可以把while中的第二个条件剥离出来,变成一个函数指针,以传入不同规则(判断数字应该在前半部分还是在后半部分)
    • STL中partition函数的做法
    • 如果要保证调整后,各自部分的相对顺序不变,则可用stable_partition函数
  • 问题举例
    • 调整数组使奇数在前,偶数在后
    • 调整数组使小于某个数(pivot)的数在前,大于的在后
    • 调整数组使负数在前,非负数在后
    • 调整数组使能被3整数的数在前,不能整数的在后
 
 

 

posted @ 2019-01-05 14:19  wikiwen  阅读(397)  评论(0编辑  收藏  举报