Design a HashSet without using any built-in hash table libraries.

Implement MyHashSet class:

  • void add(key) Inserts the value key into the HashSet.
  • bool contains(key) Returns whether the value key exists in the HashSet or not.
  • void remove(key) Removes the value key in the HashSet. If key does not exist in the HashSet, do nothing.

Example 1:

Input [ "MyHashSet ", "add ", "add ", "contains ", "contains ", "add ", "contains ", "remove ", "contains "] [[], [1], [2], [1], [3], [2], [2], [2], [2]] Output [null, null, null, true, false, null, true, null, false]

Explanation MyHashSet myHashSet = new MyHashSet(); myHashSet.add(1); // set = [1] myHashSet.add(2); // set = [1, 2] myHashSet.contains(1); // return True myHashSet.contains(3); // return False, (not found) myHashSet.add(2); // set = [1, 2] myHashSet.contains(2); // return True myHashSet.remove(2); // set = [1] myHashSet.contains(2); // return False, (already removed)

Constraints:

  • 0 <= key <= 106
  • At most 104 calls will be made to add, remove, and contains.

Note: This problem is from LeetCode.
Compiled
Executed
Correct
program main
    use hashset_mod
    implicit none

    type(MyHashSet) :: myHashSet

    call myHashSet%add(1)
    call myHashSet%add(2)
    print '(L1)', myHashSet%contains(1) ! true
    print '(L1)', myHashSet%contains(3) ! false
    call myHashSet%add(2)
    print '(L1)', myHashSet%contains(2) ! true
    call myHashSet%remove(2)
    print '(L1)', myHashSet%contains(2) ! false

end program main

module hashset_mod
    implicit none

    private
    public :: MyHashSet

    type :: MyHashSet
        integer, allocatable :: keys(:)
    contains
        procedure :: add => add_impl
        procedure :: contains => contains_impl
        procedure :: remove => remove_impl
    end type MyHashSet

contains

    subroutine add_impl(this, key)
        class(MyHashSet), intent(inout) :: this
        integer, intent(in) :: key

        if (.not. allocated(this%keys)) then
            allocate(this%keys(1))
            this%keys(1) = key
        else
            allocate(this%keys(size(this%keys)+1))
            this%keys(1:size(this%keys)-1) = this%keys(1:size(this%keys)-1)
            this%keys(size(this%keys)) = key
        end if
    end subroutine add_impl

    logical function contains_impl(this, key) result(res)
        class(MyHashSet), intent(in) :: this
        integer, intent(in) :: key

        res = any(this%keys == key)
    end function contains_impl

    subroutine remove_impl(this, key)
        class(MyHashSet), intent(inout) :: this
        integer, intent(in) :: key

        integer :: i

        do i=1, size(this%keys)
            if (this%keys(i) == key) exit
        end do

        if (i <= size(this%keys)) then
            this%keys(i:size(this%keys)-1) = this%keys(i+1:size(this%keys))
            deallocate(this%keys)
        end if
    end subroutine remove_impl

end module hashset_mod
Compiled
Executed
Correct
module MyHashSet

  implicit none

  private
  integer, parameter :: INITIAL_SIZE = 10000
  integer, parameter :: MAX_LOAD_FACTOR = 2

  type :: MyHashSet
    private
    integer, allocatable :: keys(:)
    integer :: size
    integer :: count
  contains
    procedure, public :: add
    procedure, public :: contains
    procedure, public :: remove
  end type MyHashSet

contains

  subroutine add(this, key)
    class(MyHashSet), intent(inout) :: this
    integer, intent(in) :: key

    integer :: i

    if (this%count == 0) then
      allocate(this%keys(INITIAL_SIZE))
      this%size = INITIAL_SIZE
    else if (this%count == this%size) then
      allocate(this%keys(this%size * MAX_LOAD_FACTOR))
      this%size = this%size * MAX_LOAD_FACTOR
    end if

    do i = 1, this%count
      if (this%keys(i) == key) then
        return
      end if
    end do

    this%keys(this%count + 1) = key
    this%count = this%count + 1

  end subroutine add

  function contains(this, key) result(res)
    class(MyHashSet), intent(in) :: this
    integer, intent(in) :: key
    logical :: res

    integer :: i

    res = .false.

    do i = 1, this%count
      if (this%keys(i) == key) then
        res = .true.
        exit
      end if
    end do

  end function contains

  subroutine remove(this, key)
    class(MyHashSet), intent(inout) :: this
    integer, intent(in) :: key

    integer :: i

    do i = 1, this%count
      if (this%keys(i) == key) then
        this%keys(i) = this%keys(this%count)
        this%count = this%count - 1
        exit
      end if
    end do

  end subroutine remove

end module MyHashSet

program test
  use MyHashSet
  implicit none

  type(MyHashSet) :: myHashSet

  call myHashSet%add(1)
  call myHashSet%add(2)
  print *, myHashSet%contains(1)
  print *, myHashSet%contains(3)
  call myHashSet%add(2)
  print *, myHashSet%contains(2)
  call myHashSet%remove(2)
  print *, myHashSet%contains(2)

end program test
🌐 Data from online sources
class MyHashSet:

    def __init__(self):
        self.storage = [False] * 1000001

    def add(self, key: int):
        self.storage[key] = True

    def remove(self, key: int):
        self.storage[key] = False

    def contains(self, key: int) -> bool:
        return self.storage[key]
The simplest way to implement a HashSet without using any built-in hash table libraries is to use an array of boolean values. The index of the array represents the key and the value at that index represents whether the key is present in the HashSet or not. In this case, we know the key range is `0 <= key <= 10^6`, so we can create an array with a length of `1000001`.

For the add(key) method, we set the value at the index of the key to be true. For the remove(key) method, we set the value at the index of the key to be false. For the contains(key) method, we check the value at the index of the key and return it.

The implementations of these methods are straightforward, and they are similar in each language. We create a storage array (vector in C++, boolean array in Java, list in Python, and array in JavaScript), and then we use simple array operations to manipulate the data.

🌐 Data from online sources
class MyHashSet {
public:
    vector<bool> storage;

    MyHashSet() : storage(1000001, false) { }

    void add(int key) {
        storage[key] = true;
    }

    void remove(int key) {
        storage[key] = false;
    }

    bool contains(int key) {
        return storage[key];
    }
};
The simplest way to implement a HashSet without using any built-in hash table libraries is to use an array of boolean values. The index of the array represents the key and the value at that index represents whether the key is present in the HashSet or not. In this case, we know the key range is `0 <= key <= 10^6`, so we can create an array with a length of `1000001`.

For the add(key) method, we set the value at the index of the key to be true. For the remove(key) method, we set the value at the index of the key to be false. For the contains(key) method, we check the value at the index of the key and return it.

The implementations of these methods are straightforward, and they are similar in each language. We create a storage array (vector in C++, boolean array in Java, list in Python, and array in JavaScript), and then we use simple array operations to manipulate the data.