简体   繁体   中英

How to get a random element from an implemented set?

I am implementing my own Set called RandomizedSet using a technique called open hashing. I have to create a function that returns me a random element in my set, with the condition that all elements must have the same probability of being chosen and the average of this function should be O(1) time. This is how my code looks.

My class SetNode

class SetNode{
    int val;
    SetNode next;

    public SetNode(int x){
        val = x;
    }
}

My class RandomizedSet

class RandomizedSet {
    int size;
    ArrayList<SetNode> buckets;
    int numBuckets;

    /** Initialize your data structure here. */
    public RandomizedSet() {
        size = 0;
        numBuckets = 10;
        buckets = new ArrayList<>();
    }

    /** Returns the index in the ArrayList where the value will be found */
    public int getBucketIndex(int val){
        String str = Integer.parseInt(val);
        int hashcode = Math.abs(str.hashCode());
        return hashcode % numBuckets;
    }

    /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
    public boolean insert(int val) {
        int index = getBucketIndex(val);
        SetNode head = buckets.get(index);

        while(head != null){
            if(head.val == val){
                return false;
            }
            head = head.next;
        }

        size++;
        head = buckets.get(index);
        SetNode temp = new SetNode(val);
        temp.next = head;
        buckets.set(index, temp);

        if((1.0*size)/numBuckets >= 0.7){
            doubleSize();
        }

        return true;
    }

    /** Doubles the size of the ArrayList to include more nodes */
    public doubleSize(){
        ArrayList<NodeSet> temp = buckets;
        buckets = new ArrayList<>();
        numBuckets = 2*numBuckets;
        for(int i = 0; i < numBuckets; i++){
            buckets.add(null);
        }
        for(SetNode s : temp){
            SetNode head = s;
            while(head != null){
                insert(head.val);
                head = head.next;
            }
        }
    }

    /** Removes a value from the set. Returns true if the set contained the specified element. */
    public boolean remove(int val) {
        int index = getBucketIndex(val);
        SetNode head = buckets.get(index);
        SetNode prev = null;

        while(head != null){
            if(head.val == val){
                break;
            }
            prev = head;
            head = head.next;
        }

        if(head == null){
            return false;
        }

        size--;
        if(prev != null){
            prev.next = head.next;
        }
        else{
            buckets.set(index, head.next;)
        }
        return true;

    }

    /** Get a random element from the set. */
    public int getRandom() {
    }
}

My main thought to make the function getRandom() was to generate a random number between 0 and numBuckets , but this is not going to work since I can have empty buckets (those filled with null) and plenty of elements in a single bucket, so the probability won't be equal.

Any thoughts about how can I approach it?

I'm pretty new to Java, but I'm pretty sure this should work. Create a while loop and generate integers like you did. Once you find a bucket that has values in it, then break from the while loop. This should also have an equal spreading of the randomness.

public int getRandom() {
    while (true) {
        int random = (int) (Math.random() * (buckets.size() + 1));
        if (buckets.get(random) != null) {
                return random;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM