面試題21:調整陣列順序奇數位於偶數前面

jjjstephen發表於2020-12-20

索引請參考:系列目錄
題目:

  • 輸入一個整數陣列,實現一個函式來調整該陣列中數字的順序,使得所有奇數位於陣列的前半部分,所有偶數位於陣列的後半部分
  • 示例:
  • 輸入:2,1,4,9,7,6,3,5,8
  • 輸出:1,9,7,3,5,2,4,6,8

分析:

  • 將本題分為兩種思維模式:人對陣列進行排列的模式和機器對陣列進行排列的模式
  • 人對陣列進行排列的模式:看到一組數,從前往後進行依次對比然後進行排序
  • 機器對陣列進行排列的模式:雙指標進行快速比較排序

思路1:

  • 遍歷陣列,若陣列為偶數,則元素的位置不變
    • 若陣列為奇數
      • 向前訪問一位
      • 若前一位是偶數,交換位置
      • 否則跳出比較語句(此處精髓:while語句 其作用是 當陣列判斷到有奇數時,向前訪問一位,若此時前一位為偶數,而前一位的前一位也為偶數…以此類推,均需要進行對前面的所有偶數將進行交換位置)

思路2:

  • 維護兩個指標
    • 第一個指標初始化時指向陣列的第一個數字,它只向後一定
    • 第二個指標初始化時指向陣列的最後一位,它只向前移動
  • 條件1:在2個指標相遇之前,第一個指標總是位於第二個指標的前面
  • 條件2:如果指標指向的陣列是偶數,並且第二個指標指向的數字是奇數,則交換這兩個數字

思路1:

void reOrderArray(std::vector<int> &array) {

	int size = array.size();
	for (int i = 0; i < size; i++)
	{
		while (array[i] % 2 == 1)
		{
			if (i - 1 >= 0 && array[i - 1] % 2 == 0)
			{
				int temp = array[i];
				array[i] = array[i - 1];
				array[i - 1] = temp;
				--i;
			}
			else
				break;
		}
	}
}

思路2:

void reOrderArray(vector<int> &array) {
        int begin = 0;
	    int end = array.size() - 1;

	    while (begin < end)
	    {
		    while (begin < end && array[begin] % 2 == 1)
			    ++begin;
		    while (begin < end && array[end] % 2 == 0)
			    --end;
		    if (begin < end)
		    {
			    int temp = array[begin];
			    array[begin] = array[end];
			    array[end] = temp;
		    }
	    }
    }

上述程式碼中。方法1可以通過牛客的檢測因為牛客中題目比劍指offer的題目更加苛刻:
在這裡插入圖片描述
方法2沒有通過,原因是該方法沒有辦法保證調整陣列位置後技術和偶數之間的相對位置不發生改變

方法2的演化版本:該方法用了一些迭代器的知識

void reOrderArray1(std::vector<int> &array) {

	auto begin = array.begin();
	auto end = array.end() - 1;

	while (begin < end)
	{
		while (begin < end && *begin % 2 == 1)
			++begin;
		while (begin < end && *end % 2 == 0)
			--end;
		if (begin < end)
		{
			int temp = *begin;
			*begin = *end;
			*end = temp;
		}
	}
}

評註:雖然方法二因為牛客的題目更加苛刻導致沒有完全通過,但是我們可以借鑑雙指標的思想去解決以一些問題。比如排序演算法中的希爾排序等都或多或少用到這種思想。

相關文章