有1,2,……一直到n的無序數組,求排序算法,並且要求時間復雜度為O(n),空間復雜度為O(1),使用交換,而且一次只能交換兩個數。
這個是以前看到的算法題,題目不難。但是要求比較多,排序算法中,時間復雜度為O(n)就是基數排序了。
現在介紹兩種解法:
解法一:用數組特性——下標實現交換
掃描數組,每次arr[i],arr[arr[i]-1]交換,如果arr[i]=i+1,則什么都不做。這樣交換一次保證一個數字被放到它應該被放置的位置上。最后數組有序。
#include <vector> #include <iostream> using namespace std; void swap(int& a, int& b){ a^=b; b^=a; a^=b; } vector<int>& Sort(vector<int>& vec1){ if(vec1.size()==1) return vec1; for(int i=0;i<vec1.size();){ if(vec1[i]==i+1) i++; else swap(vec1[i],vec1[vec1[i]-1]); } return vec1; } int main(){ int arr[9]={1,3,7,2,9,6,8,5,4}; vector<int> vec2(arr,arr+9); Sort(vec2); for(int i=0;i<vec2.size();i++) cout<<vec2[i]<<" "; return 0; }
上面的題目是每個數字只出現一次,如果不限制出現的次數,要求時間復雜度是O(n),空間復雜度為O(1)又該怎么做,給出數字的最大范圍假設為65536。
這個題用桶排序應該可以做。
解法二:利用count[65536](和n無關,空間復雜度為O(1))數組記錄出現的次數
那么假設有下面這些數字:
100
200
300
119
0
6
...
那么對於每個這個數字,都做在count中記錄一下:
100 => count[100]++
200 => count[200]++
300 => count[300]++
119 => count[119]++
0 => count[0]++
6 => count[6]++
最后,遍歷一邊所有這些數字就可得到0~65535每個數字的個數(在count數組中),然后再順序遍歷count數組,count[n] = m,則輸出m個n,(比如說有count[3] = 2, 那么說明有2個數字3),依次輸出,最后可得結果。