1. 程式人生 > >程式設計珠璣之生成0至n-1之間的k個不同隨機序列的擴充套件問題 --2014人人網筆試題目

程式設計珠璣之生成0至n-1之間的k個不同隨機序列的擴充套件問題 --2014人人網筆試題目

一般的思想是產生一個隨機數 arr[i] 後,和前面已經產生的arr[0]~arr[i-1]進行比較,如果有重複的就重新產生一個,該演算法的平均時間複雜度為:O(n^2) ,而最壞複雜度為無限!!

這裡我們按照程式設計珠璣上那個問題的擴充套件想法,利用空間換時間的演算法,生成隨機排列的數,此時時間複雜度為O(n)。

(1)建立一個長度為n+1的臨時陣列b,對該陣列賦值依次賦值0~n, 即b[i] = i;

(2)取一個1~n之間的隨機整數k=rand(0,n],取b[k]讀入arr[i],再將b陣列最後一個元素b[b.size-1]賦值給b[k],將b的長度減1;

程式碼實現:

/*
*BLOG:http://blog.csdn.net/wdzxl198
*AUTHOR:Atlas
*EMAIL:
[email protected]
*/ #include<iostream> using namespace std; void Random(int *arr,int length) { srand(time(NULL)); int i,randnum; int limitsize = length; int b[limitsize]; for(i=0; i<limitsize; i++) { b[i] = i+1; } for(i=0; i<length; i++) { randnum = rand()%limitsize; limitsize--; arr[i] = b[randnum]; b[randnum] = b[limitsize]; } } int main() { int arr[100]; //假使隨機出1到100的隨機數 Random(arr,100); for(int i=0;i<100;i++) { cout<<arr[i]<<" "; } cout<<endl; quickSort(arr,0,99); for(int i=0;i<100;i++) { cout<<arr[i]<<" "; } cout<<endl; system("PAUSE"); return 0; }
這種方法的是O(n)時間複雜度,但是沒有求出題目中期望的次數。
import java.util.Random;  
import java.util.Set;  
import java.util.TreeSet;  
/** 
 * #面試題#有一個數組,每次從中間隨機取一個,然後放回去,當所有的元素都被取過,返回總共的取的次數。 
 * 寫一個函式實現。複雜度是什麼。 
 * bitmap,只要一個bit就可以標記是否被取過,可參考《程式設計珠璣》的點陣圖排序 
 *  
 * 時間複雜度的話,我不太會算,以下是引用https://github.com/vyan/test/blob/master/accessTimes.cpp: 
 * 使用bit打點記錄已經取的數,  
 * 複雜度分析,假設陣列總長度為n  
 * 取到第1個之前未被取到的數的期望 E(1)=1  
 * 取到第2個之前未被取到的數的期望 E(2)=n/n-1  
 * 取到第3個之前未被取到的數的期望 E(3)=n/n-2  
 * ... 
 * 取到第n個之前未被取到的數的期望 E(n)=n/1  
 * 總得期望次數E=n+n/(n-1)+n/(n-2)+...+n/1; 
 *              =n(1+1/(n-1)+1/(n-2)+...+1/1)  
 *              =nln(n)  
 * 所以演算法平均複雜度為nlogn  
 *  
 * 下面的程式碼裡面,除法和求模運算我都用位運算來實現,事實上直接用java提供的(/,%)也可以 
 * 同時,為了驗證是否真的取到了陣列的所有元素,我用了TreeSet儲存已選中的下標(去重) 
 *  
 * 最後,還有一個問題是,可能取了很多次,都沒能全選中,這個時候可以設定一個最長時間或者最大嘗試次數,超過則結束程式, 
 * 避免程式長時間執行甚至死迴圈 
 *  
 * @author lijinnan 
 *  
 */  
public class TimesOfAccessArray {  
  
    public static final int SHIFT = 5;  
    public static final int BLOCK_SIZE = (1 << SHIFT);  //32  
    public static final int MASK = (1 << SHIFT) - 1;  //31  
  
    public static void main(String[] args) {  
        int[] array = new int[200];  
        long times = accessTimes(array);  
        System.out.println(times);  
    }  
      
    public static long accessTimes(int[] array) {  
        if (array == null || array.length == 0) {  
            return -1L;  
        }  
        long result = 0L;  
        int len = array.length;  
        int[] bitmap = new int[divide(len, BLOCK_SIZE) + 1];  
        int setTimes = 0;  
        Set<Integer> set = new TreeSet<Integer>();  
        while (setTimes < len) {  
            int pos = new Random().nextInt(len);  
            set.add(pos);  
            if (set(bitmap, pos)) {  
                setTimes++;  
            }  
            result++;  
        }  
        System.out.println(set);  
        return result;  
    }  
      
    public static boolean set(int[] bitmap, int pos) {  
        boolean result = false;  
        int blockNo = divide(pos, BLOCK_SIZE);  
        int index = mod(pos, BLOCK_SIZE);  
        boolean notExist = (bitmap[blockNo] & (1 << index))== 0;  
        if (notExist) {  
            bitmap[blockNo] |= (1 << index);  
            result = true;  
        }  
        return result;  
    }  
  
    public static boolean exist(int[] bitmap, int pos) {  
        int blockNo = divide(pos, BLOCK_SIZE);  
        int index = mod(pos, BLOCK_SIZE);  
        return (bitmap[blockNo] & (1 << index)) != 0;  
    }  
      
    private static int divide(int x, int y) {  
        return x >> offSet(y);  
    }  
  
    private static int mod(int x, int y) {  
        int z = x;  
        int i = offSet(y);  
        return z - ((z >> i) << i);  
    }  
      
    //e.g. 32=2^5, return 5 只考慮2的冪  
    private static int offSet(int y) {  
        return howManyBits(y) - 1;  
    }  
  
    //二進位制的表示裡面,有多少位。例如32是6位  
    private static int howManyBits(int y) {  
        int bitNum = 0;  
        while (y != 0) {  
            y = (y >> 1);  
            bitNum++;  
        }  
        return bitNum;  
    }  
     
  
} 

相關推薦

程式設計珠璣生成0n-1之間k不同隨機序列擴充套件問題 --2014人人筆試題目

一般的思想是產生一個隨機數 arr[i] 後,和前面已經產生的arr[0]~arr[i-1]進行比較,如果有重複的就重新產生一個,該演算法的平均時間複雜度為:O(n^2) ,而最壞複雜度為無限!! 這裡我們按照程式設計珠璣上那個問題的擴充套件想法,利用空間換時間的演算法,生成隨機排列的數,此時時間複雜度

劍指offer python版 0n-1中缺失的數字

n) style pri bsp pytho += def clas python def aa(nums,n): for i in range(n): if i ==nums[i]: i +=1 else:

【Java】 劍指offer(53-2) 0n-1中缺失的數字 《劍指Offer》Java實現合集 《劍指Offer》Java實現合集

  本文參考自《劍指offer》一書,程式碼採用Java語言。 更多:《劍指Offer》Java實現合集   題目   一個長度為n-1的遞增排序陣列中的所有數字都是唯一的,並且每個數字都在範圍0到n-1之內。在範圍0到n-1的n個數字中有且只有一個數字不在該陣列中,請找

Java架構-(十) 整合spring cloud雲架構 - SSO單點登入OAuth2.0登入認證(1)

之前寫了很多關於spring cloud的文章,今天我們對OAuth2.0的整合方式做一下筆記,首先我從網上找了一些關於OAuth2.0的一些基礎知識點,幫助大家回顧一下知識點: 一、oauth中的角色 client:呼叫資源伺服器API的應用 Oauth 2.0 Provide

劍指Offer 0n-1中缺失的數字

題目: 一個長度為n-1的遞增排序陣列中的所有數字都是唯一的,並且每個數字都在範圍0到n-1之內。 在範圍0到n-1的n個數字中有且只有一個數字不在該陣列中,請找出這個數字。 樣例 輸入:[0,1,2,4] 輸出:3 解答: 這道題要注意一種情況,即缺失的數字為n-1,如 [0,

劍指-OFFER_3 java_在一個長度為n的數組裡的所有數字都在0n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。

題源:  在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。   例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字

面試題53(二):0n-1中缺失的數字

一、題目 一個長度為n-1的遞增排序陣列中的所有數字都是唯一的,並且每個數字都在範圍0到n-1之內。在範圍0到n-1的n個數字中有且只有一個數字不在該陣列中,請找出這個數字。 二、關鍵 三、解釋 1.解題思想:基於二分查詢的思想來查詢,如果中間元素的值和下標相等,那麼

(十)Java B2B2C o2o多使用者商城 springcloud架構- SSO單點登入OAuth2.0登入認證(1)

之前寫了很多關於spring cloud的文章,今天我們對OAuth2.0的整合方式做一下筆記,首先我從網上找了一些關於OAuth2.0的一些基礎知識點,幫助大家回顧一下知識點:Spring Cloud大型企業分散式微服務雲構建的B2B2C電子商務平臺原始碼企鵝求求: 貳一四七七七五六叄叄 一、

隨機生成0n之間的m個數

如何用隨機數生成0到n之間的m個不重複的數 1、最直接的方法就是先隨機生成一個0到n之間的數,判斷這個數是否已被選上,如果以前沒選過,則選上,如果以前已選,則丟棄 void common(int n,int m) { int * randnum=(int *)mallo

我們程式設計 C++學習手冊v0.1

我們程式設計吧 之 cpp 學習手冊 * Version 0.1 * 轉義字元的使用 參考程式escape_char.cpp typedef與#define 的區別 typedef的用法 typedef常用來定義一個識別符號及關鍵字的別名,它

Java併發程式設計系列十:synchronized(1

在多執行緒併發訪問資源(這類資源稱為臨街資源)的時候,由於割裂來了原子操作,所以會導致資料不一致的情況。為了避免這種情況,需要使用同步機制,同步機制能夠保證多執行緒併發訪問資料的時候不會出現資料不一致的情況。 一種同步機制是使用synchronized關鍵字,

劍指Offer-題53(二)(Java版):0n-1中缺失的數字

參考自:《劍指Offer——名企面試官精講典型程式設計題》 題目:0到n-1中缺失的數字 一個長度為n-1的遞增排序陣列中的所有數字都是唯一的,並且每個數字都在範圍0到n-1之內。在範圍0到n-1的

程式設計珠璣第三章習題8

#include <iostream>#include <cstdio>#include <cassert>#include <cmath>#define SECTION  7#define MAX_NUM  10#define ROWS 5#define CO

程式設計珠璣第三章習題7

習題描述:7.常見的字典允許使用者查詢單詞的定義。習題2.1描述了允許使用者查詢變位詞的字典。設計查詢單詞的正確拼寫的字典和查詢單詞的押韻詞的字典。討論具有以下功能的字典:查詢整數序列(例如:1,1,2,3,5,8,13,21…)、化學結構或者歌曲韻律結構。習題解析: 1

NOI題庫答案(1.5 程式設計基礎迴圈控制)(1—20題)

01:求平均年齡 總時間限制: 1000ms        記憶體限制: 65536kB 描述 班上有學生若干名,給出每名學生的年齡(整數),求班上所有學生的平均年齡,保留到小數點後兩位。 輸入 第一行有一個整數n(1<= n <= 100),表

0n-1隨機等概率輸出m不重複的數

題目描述 假設n遠大於m,程式設計實現從0到n-1中隨機等概率的輸出m個不重複的數。 void knuth(int n,int m) { srand((unsigned int)time(0

thinkphp5.0與thinkphp3.2的幾不同處(主要寫5.0的)

5.0的入口檔案是放在public資料夾下面,所以如果要單獨配置站點,則需要選到public資料夾 模板渲染方面:5.0使用的是:return $this->fetch();(fetch裡不帶引數,是自動定位到當前操作的模板檔案,如果帶引數就跟原來的一樣) 資料庫方面:5.0在