【每天一道算法題】時間復雜度為O(n)的排序


有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),依次輸出,最后可得結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM