greedy algorithms often involve optimization and combinatorial problemsthe classic example is applying it to the traveling salesperson problemwhere greedy approach always chooses the closest destination first this shortest path strategy involves finding the best solution to local problem in the hope that this will lead to global solution the dynamic programming approach is useful when our sub problems overlap this is different from divide and conquer rather than break our problem into independent sub problemswith dynamic programmingintermediate results are cached and can be used in subsequent operations like divide and conquer it uses recursionhoweverdynamic programming allows us to compare results at different stages this can have performance advantage over divide and conquer for some problems because it is often quicker to retrieve previously calculated result from memory rather than having to recalculate it recursion and backtracking recursion is particularly useful for divide and conquer problemshoweverit can be difficult to understand exactly what is happeningsince each recursive call is itself spinning off other recursive calls at the core of recursive function are two types of casesbase caseswhich tell the recursion when to terminateand recursive cases that call the function they are in simple problem that naturally lends itself to recursive solution is calculating factorials the recursive factorial algorithm defines two casesthe base case when is zeroand the recursive case when is greater than zero typical implementation is the followingdef factorial( )#test for base case if == return make calculation and recursive call fn*factorial( - print(freturn(ffactorial(