def bottom_up_fibonacci(n: int, return_ith: bool = False) -> object:
    """Returns the nth fibonacci number if return_ith=False, else it returns a
    list containing all the ith fibonacci numbers, for i=0, ... , n.

    For example, suppose return_ith == True and n == 5, then this function
    returns [0, 1, 1, 2, 3, 5]. If return_ith == False, it returns simply 5.

    Note: indices start from 0 (not from 1).

    This function uses a dynamic programing "bottom up" approach: we start by
    finding the optimal solution to smaller sub-problems, and from there, we
    build the optimal solution to the initial problem.

    Time complexity: O(n)."""
    if n == 0:
        return n if not return_ith else [n]
    if n == 1:
        return n if not return_ith else [0, n]

    fib = [0] * (n + 1)
    fib[0] = 0
    fib[1] = 1

    for i in range(2, n + 1):
        fib[i] = fib[i - 1] + fib[i - 2]

    return fib[-1] if not return_ith else fib