1. 程式人生 > >【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 ]);      } }   連結: https://www.nowcoder.com/questionTerminal/beb5aa231adc45b2a5dcc5b62c93f593?toCommentId=460671 來源:牛客網 /**  * 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整數的數在前,不能整數的在後