0

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?

Samuel Mariña
  • 109
  • 3
  • 15
  • What is doubleSize()? it has no signature. What is **SetNode**? Why aren't you using a HashSet/HashMap to achieve O(1)? – Jason Apr 03 '20 at 01:42
  • The idea is to implement by myself a HashSet, so in order to do so, I created a SetNode class, which is node that contains its value and a pointer to a next node. I will annotate what doubleSize() means – Samuel Mariña Apr 03 '20 at 01:59

1 Answers1

0

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;
        }
    }
}
TheXDShrimp
  • 116
  • 13
  • Think about using a good development environment like Eclipse to code your programs, it helps with catching compile erros ;). – TheXDShrimp Apr 03 '20 at 04:16
  • I thought about it, but let's look at this example. Let's say I have 2 buckets, in bucket 1 I have 2 elements [elem1, elem2], in bucket 2 I have one element [elem3]. If I select a random number between 1 and 2, to choose a bucket, then there's 50% chance I get bucket 2 and therefore 50% of getting elem3, and 50% I get bucket 1, but then I have 25% chance of getting elem1, and 25% of getting elem2, therefore, possibilities are not the same – Samuel Mariña Apr 03 '20 at 06:58
  • Maybe add up all the numbers of elements in each number then generate a random number. So in your case, you would have `int total = 3` . Generate a random number and then see where that number is. For example if you generated 2, then you can see that it is not the first bucket, but it is the second bucket. – TheXDShrimp Apr 04 '20 at 16:49