ebook img

Programming Interview Problems: Dynamic Programming (with solutions in Python) PDF

181 PagesΒ·2020Β·6.406 MBΒ·English
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview Programming Interview Problems: Dynamic Programming (with solutions in Python)

1 ProgrammingInterviewProblems: DynamicProgramming(withsolutionsinPython) Copyright2020LeonardoRossi Thedesignationsofproductsandtechnologiesthatappearinthisbookmaybeclaimedas trademarksbytheirmanufacturersandsellers. While every precaution has been taken in the preparation of this book, the publisher and authorsassumenoresponsibilityforerrorsoromissions,orfordamagesresultingfromthe useoftheinformationcontainedherein. 2 Contents Contents Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Generaladvicefortheinterview . . . . . . . . . . . . . . . . . . . . . . . 6 1 TheFibonaccisequence . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Solution1: bruteforce,𝑂(2𝑛)time 7 Solution2: dynamicprogramming,top-down 9 Solution2: dynamicprogramming,bottom-up 11 2 Optimalstockmarketstrategy . . . . . . . . . . . . . . . . . . . . . . . . 13 Solution1: dynamicprogramming,top-down,𝑂(𝑛)time 13 Solution2: dynamicprogramming,bottom-up,𝑂(𝑛)time 15 Variation: limitedinvestmentbudget 16 Variation: limitednumberoftransactions 17 3 Change-making . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Clarificationquestions 20 Solution1: dynamicprogramming,top-down,𝑂(𝑛𝑣)time 20 Solution2: dynamicprogramming,bottom-up,𝑂(𝑛𝑣)time 25 Solution3: dynamicprogramming+BFS,bottom-up,𝑂(𝑛𝑣)time 26 Variant: countthenumberofwaystopay(permutations) 29 Solution: dynamic-programming,top-down,𝑂(𝑛𝑣) 29 Variant: countthenumberofwaystopay(combinations) 32 Solution: dynamic-programming,top-down,𝑂(𝑛𝑣) 32 4 Numberofexpressionswithatargetresult . . . . . . . . . . . . . . . . . . 36 Clarificationquestions 36 Solution1: brute-force,𝑂(2𝑛)time 36 Solution2: dynamicprogramming,top-down,𝑂(𝑛𝑆)time 38 Solution3: dynamicprogramming+BFS,bottom-up,𝑂(𝑛𝑆)time 39 Unittests 41 5 Partitioningasetintoequal-sumparts . . . . . . . . . . . . . . . . . . . . 43 Clarificationquestions 43 Solution1: dynamicprogramming,top-down,𝑂(𝑛𝑆)time 43 6 Splittingastringwithoutspacesintowords . . . . . . . . . . . . . . . . . . 46 Clarificationquestions 46 Solution1: dynamicprogramming,top-down,𝑂(𝑛𝑀)time 46 Solution2: dynamicprogramming+BFS/DFS,bottom-up,𝑂(𝑛𝑀)time 48 7 Thenumberofbinarysearchtrees . . . . . . . . . . . . . . . . . . . . . . 50 Solution1: dynamicprogramming,top-down,𝑂(𝑛2)time 50 8 Themaximum-sumsubarray . . . . . . . . . . . . . . . . . . . . . . . . 55 Clarificationquestions 55 Solution1: dynamicprogramming,𝑂(𝑛)time,𝑂(𝑛)space 55 Solution2: dynamicprogramming,𝑂(𝑛)time,𝑂(1)space 61 Unittests 61 9 Themaximum-productsubarray . . . . . . . . . . . . . . . . . . . . . . . 63 Clarificationquestions 63 Solution1: greedy,two-pass,𝑂(𝑛)time 63 Contents 3 Solution2: dynamicprogramming,one-pass,𝑂(𝑛)time 69 Unittests 73 10 Shortestpairofsubarrayswithtargetsum . . . . . . . . . . . . . . . . . . 75 Clarificationquestions 75 Solution1: dynamicprogramming+slidingwindow,𝑂(𝑛)time,𝑂(𝑛)space 75 11 Longestpalindromicsubstring . . . . . . . . . . . . . . . . . . . . . . . . 81 Clarificationquestions 81 Solution1: bruteforce,𝑂(𝑛3) 81 Checkingifastringisapalindrome 81 Checkingifastringisapalindrome: afasterway 83 Puttingitalltogether 83 Solution2: dynamicprogramming,𝑂(𝑛2) 84 Solution3: dynamicprogramming,𝑂(𝑛) 88 Unittests 90 12 Longestvalidparenthesessubstring . . . . . . . . . . . . . . . . . . . . . 92 Clarificationquestions 92 Solution1: dynamicprogramming,bottom-up,𝑂(𝑛) 92 Solution3: dynamicprogramming,top-down,𝑂(𝑛) 97 Unittests 98 13 Longestincreasingsubsequence . . . . . . . . . . . . . . . . . . . . . . .100 Clarificationquestions 100 Solution1: dynamicprogramming,bottom-up,𝑂(𝑛2)time,𝑂(𝑛2)space 100 Solution2: dynamicprogramming,bottom-up,𝑂(𝑛2)time,𝑂(𝑛)space 103 Variant: countthenumberofsolutions 105 Solution: dynamicprogramming,bottom-up,𝑂(𝑛2)time,𝑂(𝑛)space 105 14 Longestarithmeticsubsequence . . . . . . . . . . . . . . . . . . . . . . .108 Clarificationquestions 108 Solution1: dynamicprogramming,bottom-up,𝑂(𝑛2)time,𝑂(𝑛2)space 108 Unittests 112 15 Dealingthebesthandofcards . . . . . . . . . . . . . . . . . . . . . . . .114 Clarificationquestions 114 Solution1: bruteforce,𝑂(𝑛2)time 114 Solution2: dynamicprogramming,𝑂(𝑛)time 115 Unittests 116 16 Numberofwaystoclimbstairs . . . . . . . . . . . . . . . . . . . . . . .118 Clarificationquestions 118 Solution1: dynamicprogramming,top-down,𝑂(𝑛)time 118 Solution2: dynamicprogramming,bottom-up,𝑂(𝑛)time 119 Solution3: dynamicprogramming,bottom-up,𝑂(1)time 119 Unittests 120 17 Numberofpathsthroughmaze . . . . . . . . . . . . . . . . . . . . . . .121 Clarificationquestions 121 Solution1: dynamicprogramming,top-down,𝑂(𝑛2)time 121 Solution2: dynamicprogramming,bottom-up,𝑂(𝑛2)time 124 Solution3: dynamicprogramming,bottom-up,𝑂(𝑛2)time,linearspace 125 4 Contents Unittests 126 18 Maximum-scorepaththroughmaze . . . . . . . . . . . . . . . . . . . . .129 Clarificationquestions 129 Solution1: dynamicprogramming,top-down,𝑂(𝑛2)time 129 Solution2: dynamicprogramming,bottom-up,𝑂(𝑛2)time 132 Solution3: dynamicprogramming,bottom-up,𝑂(𝑛2)time,linearspace 133 Unittests 134 19 Subarraysum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .137 Clarificationquestions 137 Solution1: brute-force,𝑂(π‘šπ‘›) 137 Solution2: dynamicprogramming,𝑂(π‘š+𝑛) 137 20 Submatrixsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .139 Clarificationquestions 139 Solution1: brute-force,𝑂(π‘šπ‘›2) 139 Solution2: dynamicprogramming,𝑂(π‘š+𝑛2) 140 Unittests 144 21 Largestsquaresubmatrixofones . . . . . . . . . . . . . . . . . . . . . . .148 Clarificationquestions 148 Solution1: brute-force,𝑂(𝑛5) 148 Solution2: dynamicprogramming,𝑂(𝑛2) 150 22 Largestrectangleinskyline . . . . . . . . . . . . . . . . . . . . . . . . .154 Clarificationquestions 154 Solution1: brute-force,𝑂(𝑛3) 154 Solution2: dynamicprogramming,𝑂(𝑛2) 155 Solution3: dynamicprogramming+stack,𝑂(𝑛) 156 23 Largestsubmatrixofones . . . . . . . . . . . . . . . . . . . . . . . . . .162 Clarificationquestions 162 Solution1: brute-force,𝑂(𝑛6) 162 Solution2: dynamicprogramming,𝑂(𝑛3) 163 Solution3: dynamicprogramming,𝑂(𝑛2) 166 24 Interleavedstrings . . . . . . . . . . . . . . . . . . . . . . . . . . . . .168 Clarificationquestions 168 Solution1: brute-force,𝑂(2𝑛) 168 Solution2: dynamicprogramming,𝑂(𝑛2) 172 25 Regularexpressionmatching . . . . . . . . . . . . . . . . . . . . . . . .174 Clarificationquestions 174 Solution1: brute-force,𝑂(2𝑛) 174 Solution2: dynamicprogramming,𝑂(𝑛2) 178 Unittests 180 Contents 5 Preface Overthelastdecade, manycompanieshaveadoptedtheFANG-styleinterviewprocessfor softwareengineerpositions: programmingquestionsthatinvolveanalgorithmdesignstep, andoftenrequirecompetitiveprogrammingsolvingtechniques. Theadvantagesanddisadvantagesofthisstyleofinterviewquestionsarehighlydebated,and outsidethescopeofthisbook. Whatisimportantisthatthequestionsthatareaskedpose seriouschallengestocandidates,thusrequirethoroughpreparation. Theclassofproblemsthatarebyfarthemostchallengingisdynamicprogramming. Thisis duetoacombinationofdynamicprogrammingbeingrarelyusedinday-to-daywork,andthe difficultyoffindingasolutioninashortamountoftime,whennothavingpriorexperience withthismethod. This book presents 25 dynamic programming problems that are most commonly encoun- tered in interviews, and several oftheirvariants. For eachproblem, multiple solutionsare given,includingagradualwalkthroughthatshowshowonemayreachtheanswer. Thegoal isnottomemorizesolutions,buttounderstandhowtheyworkandlearnthefundamental techniques,suchthatnew,previouslyunseenproblemscanbesolvedwithease. The solutions are very detailed, showing example walkthrougs, verbal explanations of the solutions,andmanydiagramsanddrawings. Theseweredesignedinawaythathelpsboth verbal and visual learners grasp the material with ease. The code implementation usually comeslast,accompaniedbyunittestsandcomplexity/performanceanalysis. Aparticularfocushasbeenputoncodeclarityandreadability: duringtheinterview,weare expectedtowritecodeaswewouldonthejob. Thismeansthatthecodemustbetidy,with well-namedvariables,shortfunctionsthatdoonething,modularity,commentsdescribing why we do certain things etc. This is, sadly, unlike most other material on dynamic pro- grammingthatonemayfindonline,incompetitiveprogrammingresources,oreveninwell- knownalgorithmdesigntextbooks. Infact,thepoorstateofthematerialonthistopicisthe mainreasonIwrotethisbook. Ihopethatyoufindthisbookusefulforpreparingtogetthejobyouwishfor. Whetheryou likethebookornot,Iwouldappreciateyourfeedbackthroughabookreview. Goodluckwithyourinterviews! 6 Contents Generaladvicefortheinterview Findoutinadvancewhatkindofquestionswillbeasked. Usually,theyareinoneormore of the following categories: coding, algorithm design (with or without implementation), domain-specific questions, theoretical questions, behavioral questions, live coding, debug- ging,one-dayassignmentsorpairprogramming. Youshouldknowwhatyouneedtoprepare for. Forprogrammingquestions,donotjumpdirectlytowritingcode,evenifthesolutionlooks obvious. First,askclarificationquestionsandgooversomesimpleexamples,tomakesure youunderstandtherequirementswell. Then,youmaysketchasolutionanddiscussitwith the interviewer. Several iterations might be needed in case of correctness or performance issues. Onlyoncetheyagreethatthesolutionlooksfine,proceedwithimplementingit. Treattheinterviewquestionsnotlikeproblems,butrealjobassignments.Takethemseriously andsolvethemthoroughly,likeaprofessional. Treat your interviewers as colleagues, with whom you must work together to solve the as- signment. Shiftintothemindsetthatyouarealreadyonthesameteam. Discussandinteract withthemthesamewayyouwouldwithcolleaguesonthejob. Write tidy, clean codeβ€”as much as possible given the time you have. Try to follow typi- calcodingstyleguidelinesforyourlanguage. ForPython, youcanfindgoodguidelinesat www.python.org/dev/peps/pep-0008andgoogle.github.io/styleguide/pyguide.html. Donotforgettoaskaboutthesizeofthedatayourcodeneedstohandleβ€”thisisimportant todeterminethetimecomplexityofyoursolution. Ifyoucannotfindthefastestalgorithmneededtosolvetheproblem,proposeaslowerone. Sometimesyoumightgetanidea(orahintfromtheinterviewer)tomakeitfasteronceyou writeit. Butevenifyoudonot,anysolutionisbetterthannosolution. Trytobequickinyouranswer. Interviewersusuallyplantoaskfollow-upquestions. Ifyou donothavesufficienttimeleftforthese,yourresultmaybepoor,evenifyouansweredthe originalquestionwell. 7 1 TheFibonaccisequence Returnthen-thnumberintheFibonaccisequence. ThefirsttwonumbersintheFibonacci sequenceareequalto1;anyothernumberisequaltothesumoftheprecedingtwonumbers. Example: forn=6,thefirst6numbersofthesequenceare[1, 1, 2, 3, 5, 8]sotheresult is8. Solution1: bruteforce,𝑂(2𝑛)time Astraightforwardsolutionistoimplementthefunctionrecursively: def fibonacci(n): if n <= 2: return 1 return fibonacci(n Β­ 1) + fibonacci(n Β­ 2) Theabovecodeiscorrectbuttooslowduetoredundancies. Wecanseethisifweaddlogging tothefunction: import inspect def stack_depth(): return len(inspect.getouterframes(inspect.currentframe())) Β­ 1 def fibonacci(n): print("{indent}fibonacci({n}) called".format( indent=" " * stack_depth(), n=n)) if n <= 2: return 1 return fibonacci(n Β­ 1) + fibonacci(n Β­ 2) fibonacci(6) Wechangedthecodetoprinttheargumentpassedtothefibonaccifunction. Themessage isindentedbythecallstackdepth, sothatwecanseebetterwhichfunctioncalliscausing whichsubsequentcalls. Runningtheabovecodeprints: fibonacci(6) called fibonacci(5) called fibonacci(4) called fibonacci(3) called fibonacci(2) called fibonacci(1) called fibonacci(2) called fibonacci(3) called fibonacci(2) called fibonacci(1) called fibonacci(4) called 8 1 TheFibonaccisequence fibonacci(3) called fibonacci(2) called fibonacci(1) called fibonacci(2) called That’salotofcalls! Ifwedrawthecallgraph,wecanseethatit’sanalmostfullbinarytree: 9 Notice that the height of the binary tree is n (in this case, 6). The tree is almost full, thus it has 𝑂(2𝑛) nodes. Since each node represends a call of our function, our algorithm has exponentialcomplexity. Solution2: dynamicprogramming,top-down Wecanoptimizetheprevioussolutionbyavoidingredundantcomputations. Theseredun- danciesarevisibleinthecallgraph: β€’ fibonacci(4)iscalledtwice,oncebyfibonacci(5)andoncebyfibonacci(6); β€’ fibonacci(3)iscalled3times; β€’ fibonacci(2)iscalled5times; β€’ fibonacci(1)iscalled3times. Itdoesnotmakesensetocompute, forexample, the4-thFibonaccinumbertwice, sinceit doesnotchange. Weshouldcomputeitonlyonceandcachetheresult. Let’suseadictionarytostorethecache: fibonacci_cache = {} def fibonacci(n): if n <= 2: return 1 if n not in fibonacci_cache: fibonacci_cache[n] = fibonacci(n Β­ 1) + fibonacci(n Β­ 2) return fibonacci_cache[n] Thecallgraphoftheoptimizedcodelookslikethis: Notice how only the first call to fibonacci(n) recurses. All subsequent calls return from thecachethevaluethatwaspreviouslycomputed. Thisimplementationhas𝑂(𝑛)timecomplexity,sinceexactlyonefunctioncallisneededto computeeachnumberintheseries. 10 1 TheFibonaccisequence Thisstrategyofcachingtheresultsofsubproblemsiscalleddynamicprogramming. Whiletheabovecodeiscorrect,therearesomecodestyleissues: β€’ We introduced the global variable fibonacci_cache; it would be great if we could avoidglobalvariables,sincetheyimpactcodereadability; β€’ Thecodeismorecomplicatedthanbeforeduetothecachemanipulations. We can avoid adding the global variable by using instead an attribute called cache that is attachedtothefunction: def fibonacci(n): if n <= 2: return 1 if not hasattr(fibonacci, 'cache'): fibonacci.cache = {} if n not in fibonacci.cache: fibonacci.cache[n] = fibonacci(n Β­ 1) + fibonacci(n Β­ 2) return fibonacci.cache[n] Theadvantageisthatthecachevariableisnowownedbythefunction,sonoexternalcode isneededanymoretoinitializeit. Thedisadvantageisthatthecodehasbecomeevenmore complicated,thushardertoreadandmodify. Abetterapproachistokeeptheoriginalfunctionsimple,andwrapitwithadecoratorthat performsthecaching: def cached(f): cache = {} def worker(*args): if args not in cache: cache[args] = f(*args) return cache[args] return worker @cached def fibonacci(n): if n <= 2: return 1 return fibonacci(n Β­ 1) + fibonacci(n Β­ 2) Thegood newsisthatPython3 hasbuilt-insupport forcachingdecorators, so thereisno needtorollyourown: from functools import lru_cache @lru_cache(maxsize=None) def fibonacci(n): if n <= 2:

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.