def counting_sort(numbers):
    """Sort given numbers (integers) by counting occurrences of each number,
    then looping over counts and copying that many numbers into output list.
    Running time: O(n + k) where k is the range of numbers, because if k is really high then affects the run time significantly. 
    Memory usage: O(k) because the number of total arrays is equal to the value of k"""

    # creating a temp array with 0, times however many based on the max value of numbers + 1 b/c indexing starts at 1
    temp_array = [0] * (max(numbers) + 1)
    # loop through numbers
    for num in numbers:
        # if the temp array's index of that number is 0 - meaning it's empty then set it to be 1
        if temp_array[num] == 0:
            temp_array[num] = 1
        # else there's already something in there so just add one to it
        else:
            temp_array[num] += 1

    numbers = []

    # loop through the temp_array
    for y in range(len(temp_array)):
        # if it's index is not equal to 0 then we add the count; and looping until it's index value is 0
        while temp_array[y] != 0:
            numbers.append(y)
            temp_array[y] -= 1

    return numbers