洗牌程序(面試常問)

Solution 1(時間複雜度約爲O(n^2),空間複雜度爲O(n))

#include <iostream>
#include<cstdlib>
#include<vector>
#define N 54
using namespace std;
void func(vector<int>&num){
     int hash[N+1]={0};
     int cnt=0,i=0;
     while(cnt<N){
        int val=rand()%N+1;
        if(!hash[val]){
            num[i++]=val;
            hash[val]=1;
            ++cnt;
        }
     }
     return ;
}
int main()
{
    vector<int>data(N);
    func(data);
    for(int i=0;i<N;++i)
        cout<<data[i]<<" ";
    cout<<endl;
    return 0;
}

Solution 2(時間複雜度約爲O(n),空間複雜度爲O(1))

Knuth-Durstenfeld Shuffle算法

Knuth 和 Durstenfeld  在Fisher 等人的基礎上對算法進行了改進,在原始數組上對數字進行交互,省去了額外O(n)的空間。該算法的基本思想和 Fisher 類似,每次從未處理的數據中隨機取出一個數字,然後把該數字放在數組的尾部,即數組尾部存放的是已經處理過的數字。

算法步驟爲:

1. 建立一個數組大小爲 n 的數組 arr,分別存放 1 到 n 的數值;

2. 生成一個從 0 到 n - 1 的隨機數 x;

3. 輸出 arr 下標爲 x 的數值,即爲第一個隨機數;

4. 將 arr 的尾元素和下標爲 x 的元素互換;

5. 同2,生成一個從 0 到 n - 2 的隨機數 x;

6. 輸出 arr 下標爲 x 的數值,爲第二個隨機數;

7. 將 arr 的倒數第二個元素和下標爲 x 的元素互換;

……

如上,直到輸出n個數爲止

時間複雜度爲O(n),空間複雜度爲O(1),缺點必須知道數組長度n。

#include <iostream>
#include<cstdlib>
#include<vector>
#define N 54
using namespace std;
void xipai(vector<int>&data){
    int cnt;
    for(int i=0;i<N;++i){
        cnt=rand()%(N-i);
        swap(data[cnt],data[N-i-1]);
    }
    return ;
}
int main()
{
    vector<int>data(N);
    for(int i=0;i<N;++i)
        data[i]=i+1;
    xipai(data);
    for(int i=0;i<N;++i)
        cout<<data[i]<<" ";
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章