數組中的排序分析及奇偶排序 - 算法數據結構面試分享(四)
我們之前在課本上學習過一般的排序方法,如冒泡,快排,插入,歸並。其中時間復雜度有O(N), 和O(Nlogn), 以及O(N2)的。今天我們在這裏看一些特定情況下的排序,並否所有的排序都是基於大小的,有時待排序的數大小範圍是已知的,我們分別看兩個典型的例子:
- 給你一個整型的數組,我想把奇數排在前面,偶數排在後面,也就是沒有任何一個偶數出現在奇數的前面。
- 給你一個整型數組,裏面出現的數在[0-100] 之間,能用最優化的方法幫我排序嗎
我們今天先看第一個問題。還是按照之前的六部曲。
1. 確保我們理解了問題,並且嘗試一個例子,確認理解無誤。
題目當中已經把需求給細化了,沒有任何一個偶數排在奇數的前面。舉個例子 {1,2,3,4,5}會排成 {1,3,5,4,2}。 當然這裏還有一個問題需要確認清楚,我們關心它的大小嗎?即奇數和偶數部分都需要時升序的嗎? 這裏可以告訴大家,我們可以忽略這個,這道題目中中只關心奇偶。
2. 想想你可以用什麽方法解決問題,你會選擇哪一種,為什麽?
拿到這道題,我們首先想到的是如何判斷奇偶數。但這其實不是本題的重點。一個很簡單的方法出來了,我申明兩個數組,一個保存奇數,另一個保存偶數,再把兩個數組做一個合並並返回就好了。這個方法是可行的,再挑奇偶時,其實我們只需要掃描數組一遍,不過我們浪費了存儲空間,至少我們需要另外申明兩個臨時的數組。而且,我們還無法事先知道奇數和偶數的數組應該是多長。是不是有更好的辦法呢?
我們再看下之前的例子,看能不能找到什麽蹊蹺的地方? {1,2,3,4,5} 從前往後,其實1是不用動的,2確定要往後挪?動,放到哪裏呢?具體位置無所謂,但是保證它的後面沒有奇數就好了。再從後往前,5是奇數,確定要往前放。到目前為止,如果我們能交換2和5問題就完美的解決了。沒錯,我們就是要從前往後依次找出偶數, 再從後往前找到奇數,再交換。再找下一個。如果采取這種方法的話,我們掃描數組一遍就可以解決問題了。
3. 解釋你的算法和實現的方法
從上面的分析看,我們只需要定個兩個臨時變量就好了。一個從前往後,一個從後往前,終止的條件是他們相遇。 再定義一個臨時變量,負責交換就好了。
4. 寫代碼的時候,記住,一定要解釋你現在在幹什麽
那我們就直接上代碼啦。
public static void Switch(int[] array) { if (array != null && array.Length > 1) { int begin = 0; int end = array.Length - 1; while (begin < end) { if (array[begin] % 2 == 0) // 偶數 { if (array[end] % 2 == 1) //奇數 { //交換 int temp = array[end]; array[end] = array[begin]; array[begin] = temp; begin++; end--; } else { end--; } } else { begin++; } } } }
在上面的代碼中有一個地方可以優化,當我們找到前面待交換的偶數,再確定後面是否有奇數時,我們總是會將後面的指針往前移動。所以end -- 可以移出來,將外面的else也刪掉。
5. Workthrough
6. 修復缺陷
我們一起來測試一下這個方法
static void Main(string[] args)
{
int[] array = new int[] { 1, 2, 3, 4, 5 };
Switch(array);
foreach (var a in array)
{
Console.WriteLine(a);
}
}
大功告成了哈。歡迎大家關註我的公眾號,還有我的系列專題課程
- 視頻教程
- 數據結構與算法
- 經典算法面試題輔導
- 排序專題講解
- 鏈表專題講解
大家有什麽更好的解法,也歡迎討論哈。
數組中的排序分析及奇偶排序 - 算法數據結構面試分享(四)