• 【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整数的数在前,不能整数的在后
     
     
  • 相关阅读:
    文件包含漏洞
    任意文件上传
    改变弱口令威胁,从意识开始
    Node.js学习笔记10--Express搭网站(2)
    Node.js学习笔记9——Express框架
    Node.js学习笔记8
    Node.js学习笔记7-文件系统
    node.js学习笔记6
    node.js学习笔记5——核心模块1
    Node.js学习4
  • 原文地址:https://www.cnblogs.com/wikiwen/p/10224374.html
Copyright © 2020-2023  润新知