一題算法|求隨機數索引

題目描述

給定一個可能含有重複元素的整數數組,要求隨機輸出給定的數字的索引。 您可以假設給定的數字一定存在於數組中。

注意
數組大小可能非常大。 使用太多額外空間的解決方案將不會通過測試。

題目示例


int[] nums = new int[] {1,2,3,3,3};
Solution solution = new Solution(nums);

// pick(3) 應該返回索引 2,3 或者 4。每個索引的返回概率應該相等。
solution.pick(3);

// pick(1) 應該返回 0。因爲只有nums[0]等於1。
solution.pick(1);

這題目中有一個地方需要注意,每一個索引返回的概率都是相同的。比較笨的方法就是將與 target 相等的元素存放到一箇中間集合中,最後從中間集合隨機取一個。第二種辦法就是利用蓄水池抽樣法來解決這個問題。

解法一:使用中間集合

我們先從頭到尾遍歷數組,將與 target 相等元素的索引,集中存儲到中間集合 list 中,最後再從中間集合中隨機返回一個元素索引。

1、解題代碼:

class Solution {

    private int[] nums;

    public Solution(int[] nums) {
        this.nums = nums;
    }


    public int pick(int target) {
        // 開闢一箇中間集合
        List<Integer> list = new ArrayList<>();

        for (int i = 0; i < nums.length; i++) {
            // 找出與target相等的元素
            if (nums[i] == target) {
                list.add(i);
            }
        }

        // 如果只存在一個,就直接返回
        if (list.size() == 1) return list.get(0);
        // 如果有兩個以上,隨機取一個
        return getRandomIndex(list);
    }


    /**
     * 隨機給出下標
     *
     * @param list 給定元素的索引集合
     * @return
     */
    public int getRandomIndex(List<Integer> list) {
        return list.get(new Random().nextInt(list.size()));
    }
}

複雜度分析

時間複雜度:需要遍歷一次數組,所以時間複雜度是O(N)

空間複雜度:使用了 ArrayList ,ArrayList 的大小與數組有關,所以空間複雜度爲O(N)

解法二:蓄水池抽樣算法

這是我在 leetcode 上看到的解法,蓄水池抽樣算法好像是一種專業的算法,關於算法的詳情,大家就自行百度,我也不是太清楚,這裏我就簡單的描述:給定一個數據流,數據流長度N很大,且N直到處理完所有數據之前都不可知,請問如何在只遍歷一遍數據(O(N))的情況下,能夠隨機選取出m個不重複的數據。符合我們的題意,這裏我就直接給出解題代碼,具體的也不是很清楚,不過刷題不就是擴寬思維嗎?

1、解題代碼

class Solution {

    private int[] nums;

    public Solution(int[] nums) {
        this.nums = nums;
    }

    public int pick(int target) {
        // 返回下標,沒找到就返回-1
        int index = -1;
        // 記錄查找到的個數
        int count = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                count++;
                // 隨機返回,new Random().nextInt() % count == 0 作爲概率
                if (new Random().nextInt() % count == 0) index = i;
            }
        }

        return index;
    }

}

複雜度分析

時間複雜度:需要遍歷一次數組,所以時間複雜度是O(N)

空間複雜度:沒有使用新的集合,所以空間複雜度爲O(1)

最後

歡迎掃碼關注微信公衆號:「平頭哥的技術博文」,和平頭哥一起學習,一起進步。

平頭哥的技術博文

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