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

【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 ]);                          // 交换以使满足枢轴规律
     } // 最后结果是 left right 均指向枢轴位置
    swap ( a [ left ], a [ pivot ]); // 将枢轴移动到位
     return left ;              // 返回枢轴位置
}
 
推广:
  • 可以把while中的第二个条件剥离出来,变成一个函数指针,以传入不同规则(判断数字应该在前半部分还是在后半部分)
    • STL中partition函数的做法
    • 如果要保证调整后,各自部分的相对顺序不变,则可用stable_partition函数
  • 问题举例
    • 调整数组使奇数在前,偶数在后
    • 调整数组使小于某个数(pivot)的数在前,大于的在后
    • 调整数组使负数在前,非负数在后
    • 调整数组使能被3整数的数在前,不能整数的在后
 
 

 

posted @ 2019-01-05 14:19 wikiwen 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值