input: Write a python function to find all prime numbers in a given range using the Sieve of Eratosthenes algorithm.
  assert sieve_of_eratosthenes(1, 20) == [2, 3, 5, 7, 11, 13, 17, 19]
  assert sieve_of_eratosthenes(10, 30) == [11, 13, 17, 19, 23, 29]
  assert sieve_of_eratosthenes(50, 100) == [53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
output: def sieve_of_eratosthenes(start, end):
      if end < 2:
          return []
      sieve = [True] * (end + 1)
      sieve[0], sieve[1] = False, False
      p = 2
      while (p * p <= end):
          if sieve[p] == True:
              for i in range(p * p, end + 1, p):
                  sieve[i] = False
          p += 1
      return [num for num in range(start, end + 1) if sieve[num]]