1. Write a recursive Python function to get the nth element of an UnorderedList. The signature should be: def getNth(UL, k): where UL is an Unordered List object and k is a positive integer. Return None if k is bigger than the length of UL. def getNth(UL, k): return getNthAux(UL.getHead(), k) def getNthAux (head, k): if not head or k < 0: return None elif k == 0: return head.getValue() else: return getNthAux(head.getNext(), k - 1) ---------------------------------------------------------------------- 2. Name at least two things that must be true for a recursive definition to be ``good.'' a. There should be one or more non-recursive base cases. b. In each recursive call, the arguments should move closer to one of the base cases to avoid an infinite computation. ---------------------------------------------------------------------- 3. Our naive recursive implementation to find the nth Fibonnaci number was horribly inefficient. In fact, it made a number of recursive calls according to the following recurrence relation: C(0) = 1 C(1) = 1 C(n) = 1 + C(n-1) + C(n-2), for n > 2 Write a direct recursive implementation in Python of this computation, i.e., compute the function C(n) in the most straightforward way. def C(n): if n == 0 or n == 1: return 1 else: return 1 + C(n-1) + C(n-2) ---------------------------------------------------------------------- 4. Now write an implementation of the computation from problem 3 that is more efficient. If you don't know how to write the code, at least explain how it works. def CHelper(k, limit, ans, ansSub1): if k >= limit: return ans else: return CHelper( k+1, limit, 1 + ans + ansSub1, ans) def CBetter(n): return CHelper(1, n, 1, 1) >>> from C import * >>> C(4) 9 >>> CBetter(4) 9 >>> C(6) 25 >>> CBetter(6) 25