[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"sanity-yixEPsE5QtSf1qJBDE4qk2pPj0GN2GVZE9uwRzs4NPM":3,"sanity-ZfgOpqFWzJ5WGChufJ400TQTtO1citwi8T5wIbZSJCs":414},{"data":4,"sourceMap":-1},{"latestPodcast":5,"latestReleases":14,"post":39,"recent":389},[6],{"_id":7,"publishedAt":8,"slug":9,"sponsored":12,"title":13},"d53f9358-3bb2-4f69-aebe-d31d19522cd4","2026-07-10T07:40:00.000Z",{"_type":10,"current":11},"slug","building-more-than-just-an-agent-harness",null,"Building more than just an agent harness",[15,21,27,33],{"_id":16,"publishedAt":17,"slug":18,"title":20},"eb5b66eb-9410-4329-83bb-22bbff39402a","2026-04-28T13:00:00.000Z",{"_type":10,"current":19},"turn-scattered-knowledge-into-trusted-intelligence","Turning scattered knowledge into trusted intelligence: Stack Internal 2026.3",{"_id":22,"publishedAt":23,"slug":24,"title":26},"369c2401-b62e-4a37-8ff8-bf603023ecad","2026-03-02T15:03:00.988Z",{"_type":10,"current":25},"what-s-new-at-stack-overflow-march-2026","What’s new at Stack Overflow: March 2026",{"_id":28,"publishedAt":29,"slug":30,"title":32},"5e9053a4-07ea-447c-91ea-29e0b6228537","2026-02-02T15:00:00.000Z",{"_type":10,"current":31},"what-s-new-at-stack-overflow-february-2026","What’s new at Stack Overflow: February 2026",{"_id":34,"publishedAt":35,"slug":36,"title":38},"a1b538eb-a8a6-46d0-80a1-ac70ec9bb935","2026-01-05T10:00:00.000-05:00",{"_type":10,"current":37},"what-s-new-at-stack-overflow-january-2026","What’s new at Stack Overflow: January 2026",{"_createdAt":40,"_id":41,"_rev":42,"_type":43,"_updatedAt":44,"author":45,"body":62,"comments":338,"dateUrl":339,"excerpt":340,"image":341,"legacyBody":344,"product":12,"publishedAt":347,"slug":348,"sponsored":12,"tags":350,"title":388,"visible":338},"2023-05-24T12:50:58Z","wp-post-19496","0aYkJXBENQTxI4C1zA8wrz","blogPost","2025-04-25T20:11:51Z",[46],{"_createdAt":47,"_id":48,"_rev":49,"_type":50,"_updatedAt":51,"avatar":52,"bio":57,"employee":58,"name":59,"slug":60},"2023-05-23T16:27:18Z","wp-author-cap-19500","dgl3SCUzppW3U2LvCoP6c0","blogAuthor","2023-06-20T15:05:12Z",{"_type":53,"asset":54},"image",{"_ref":55,"_type":56},"image-1a35ac25107b0af6163c992f8b6e7c71430227dd-1025x1025-jpg","reference","Wayne is a freelance software engineer, author, and educator. He works with iOS developers to help them pass technical interviews at top companies like Apple, Google, and Facebook. Thousands have used his book, online classes, and YouTube channel to learn new concepts, gain the necessary practice, and connect with fellow developers worldwide. He lives in Seattle, WA.","none","Wayne Bishop",{"current":61},"wayne-bishop",[63,86,95,112,131,139,143,167,175,194,197,205,213,229,232,240,248,251,259,268,276,279,287,303,311,314,322,330],{"_key":64,"_type":65,"children":66,"markDefs":81,"style":85},"7b787aedc865","block",[67,72,77],{"_key":68,"_type":69,"marks":70,"text":71},"7b787aedc8650","span",[],"If you've been programming for long enough, you've probably heard the term dynamic programming. Often a key subject in ",{"_key":73,"_type":69,"marks":74,"text":76},"7b787aedc8651",[75],"7c8036ac1c9a","technical interviews",{"_key":78,"_type":69,"marks":79,"text":80},"7b787aedc8652",[],", the idea will also come up in design review meetings or regular interactions with fellow developers. This essay will examine what dynamic programming is and why you would use it. I'll be illustrating this concept with specific code examples in Swift, but the concepts I introduce can be applied to your language of choice. Let's begin!",[82],{"_key":75,"_type":83,"href":84,"reference":12},"link","https:\u002F\u002Fwww.waynewbishop.com\u002Fcomputer-science-interview-questions","normal",{"_key":87,"_type":65,"children":88,"markDefs":93,"style":94},"c535648a7e35",[89],{"_key":90,"_type":69,"marks":91,"text":92},"c535648a7e350",[],"A way of thinking",[],"h2",{"_key":96,"_type":65,"children":97,"markDefs":111,"style":85},"81056e8c787b",[98,102,107],{"_key":99,"_type":69,"marks":100,"text":101},"81056e8c787b0",[],"Unlike specific coding syntax or design patterns, dynamic programming isn't a particular algorithm but a ",{"_key":103,"_type":69,"marks":104,"text":106},"81056e8c787b1",[105],"strong","way of thinking",{"_key":108,"_type":69,"marks":109,"text":110},"81056e8c787b2",[],". Therefore, the technique takes many forms when it comes to implementation.",[],{"_key":113,"_type":65,"children":114,"markDefs":128,"style":85},"af522041ada6",[115,119,124],{"_key":116,"_type":69,"marks":117,"text":118},"af522041ada60",[],"The main idea of ",{"_key":120,"_type":69,"marks":121,"text":123},"af522041ada61",[122],"250f8bf92ab1","dynamic programming",{"_key":125,"_type":69,"marks":126,"text":127},"af522041ada62",[]," is to consider a significant problem and break it into smaller, individualized components. When it comes to implementation, optimal techniques rely on data storage and reuse to increase algorithm efficiency. As we'll see, many questions in software development are solved using various forms of dynamic programming. The trick is recognizing when optimal solutions can be devised using a simple variable or require a sophisticated data structure or algorithm.",[129],{"_key":122,"_type":83,"href":130,"reference":12},"https:\u002F\u002Fwww.waynewbishop.com\u002Fdynamic-programming-problems",{"_key":132,"_type":65,"children":133,"markDefs":138,"style":85},"caf6503b298a",[134],{"_key":135,"_type":69,"marks":136,"text":137},"caf6503b298a0",[],"For example, code variables can be considered an elementary form of dynamic programming. As we know, a variable's purpose is to reserve a specific place in memory for a value to be recalled later.",[],{"_key":140,"_type":141,"code":142,"markDefs":12},"dffb12d6e2ad","code","\u002F\u002Fnon-memoized function\nfunc addNumbers(lhs: Int, rhs: Int) -> Int {\n   return lhs + rhs\n}\n\n\u002F\u002Fmemoized function\nfunc addNumbersMemo(lhs: Int, rhs: Int) -> Int {\n   let result: Int = lhs + rhs\n     return result\n}\n",{"_key":144,"_type":65,"children":145,"markDefs":166,"style":85},"d01f3a9ce2ea",[146,150,154,158,162],{"_key":147,"_type":69,"marks":148,"text":149},"d01f3a9ce2ea0",[],"While ",{"_key":151,"_type":69,"marks":152,"text":153},"d01f3a9ce2ea1",[141],"addNumbersMemo",{"_key":155,"_type":69,"marks":156,"text":157},"d01f3a9ce2ea2",[]," above does provide a simple introduction, the goal of a dynamic programming solution is to preserve previously seen values because the alternative could either be inefficient or could prevent you from answering the question. This design technique is known as ",{"_key":159,"_type":69,"marks":160,"text":161},"d01f3a9ce2ea3",[105],"memoization",{"_key":163,"_type":69,"marks":164,"text":165},"d01f3a9ce2ea4",[],".",[],{"_key":168,"_type":65,"children":169,"markDefs":174,"style":94},"8ddef2eed38d",[170],{"_key":171,"_type":69,"marks":172,"text":173},"8ddef2eed38d0",[],"Code challenge—Pair of numbers",[],{"_key":176,"_type":65,"children":177,"markDefs":191,"style":85},"eb5fd77e07a2",[178,182,187],{"_key":179,"_type":69,"marks":180,"text":181},"eb5fd77e07a20",[],"Over the years, I've had the chance to conduct ",{"_key":183,"_type":69,"marks":184,"text":186},"eb5fd77e07a21",[185],"aa8cc802beb1","mock interviews",{"_key":188,"_type":69,"marks":189,"text":190},"eb5fd77e07a22",[]," with dozens of developers preparing for interviews at top companies like Apple, Facebook, and Amazon. Most of us would be happy to skip the realities of the dreaded whiteboard or take-home coding project. However, the fact is that many of these brain-teaser questions are designed to test for a basic understanding of computer science fundamentals. For example, consider the following:",[192],{"_key":185,"_type":83,"href":193,"reference":12},"https:\u002F\u002Fwww.waynewbishop.com\u002Fios-interview\u002Fcslab",{"_key":195,"_type":141,"code":196,"markDefs":12},"4e585cdc67f0","\u002F*\nIn a technical interview, you've been given an array of numbers and you need to find a pair of numbers that are equal to the given target value. Numbers can be either positive, negative, or both. Can you design an algorithm that works in O(n)—linear time or greater?\n\nlet sequence = [8, 10, 2, 9, 7, 5]\nlet results = pairValues(sum: 11) = \u002F\u002Freturns (9, 2)\n*\u002F\n",{"_key":198,"_type":65,"children":199,"markDefs":204,"style":85},"2a26779e108b",[200],{"_key":201,"_type":69,"marks":202,"text":203},"2a26779e108b0",[],"As developers, we know there are usually multiple ways to arrive at a solution. In this case, the goal is knowing which numbers should be paired to achieve the expected result. As people, it's easy for us to quickly scan the sequence of numbers and promptly come up with the pair of 9 and 2. However, an algorithm will need to either check and compare each value in the sequence or develop a more streamlined solution to help us find the values we are seeking. Let's review both techniques.",[],{"_key":206,"_type":65,"children":207,"markDefs":212,"style":94},"118296a743d7",[208],{"_key":209,"_type":69,"marks":210,"text":211},"118296a743d70",[],"A brute force approach",[],{"_key":214,"_type":65,"children":215,"markDefs":228,"style":85},"348ec2e04a62",[216,220,224],{"_key":217,"_type":69,"marks":218,"text":219},"348ec2e04a620",[],"Our first approach involves looking at the first value, then reviewing each subsequent value to determine if it will provide the ",{"_key":221,"_type":69,"marks":222,"text":223},"348ec2e04a621",[105],"difference",{"_key":225,"_type":69,"marks":226,"text":227},"348ec2e04a622",[]," needed to solve the question. For example, once our algorithm checks the value of the first array item, 8, it will then scan the remaining values for 3 (e.g., 11 - 8 = 3). However, we can see the value of 3 doesn't exist, so the algorithm will repeat the same process for the next value (in our case, 10) until it finds a successful matching pair. Without going into the details of big-O notation, we can assume this type of solution would have an average runtime of O(n ^ 2)time or greater, mainly because our algorithm works by comparing each value with every other value. In code, this can be represented as follows:",[],{"_key":230,"_type":141,"code":231,"markDefs":12},"203cd5749429","let sequence = [8, 10, 2, 9, 7, 5]\n\n\u002F\u002Fnon-memoized version - O(n ^ 2)\nfunc pairNumbers(sum: Int) -> (Int, Int) {\n    \n\tfor a in sequence {\n    \t\tlet diff = sum - a\n   \t \n    \t\tfor b in sequence {\n        \t\tif (b != a) && (b == diff) {\n            \t\treturn (a, b)\n        \t\t}\n    \t\t}\n\t}    \n\treturn (0, 0)\n}\n",{"_key":233,"_type":65,"children":234,"markDefs":239,"style":94},"2f04734d4090",[235],{"_key":236,"_type":69,"marks":237,"text":238},"2f04734d40900",[],"A memoized approach",[],{"_key":241,"_type":65,"children":242,"markDefs":247,"style":85},"ae9f1f82e98b",[243],{"_key":244,"_type":69,"marks":245,"text":246},"ae9f1f82e98b0",[],"Next, let's try a different approach using the idea of memoization. Before implementing our code, we can brainstorm how storing previously seen values will help streamline the process. While using a standard array is feasible, a set collection object (also referred to as a hash table or hash map) could provide an optimized solution.",[],{"_key":249,"_type":141,"code":250,"markDefs":12},"048890144d18","\u002F\u002Fmemoized version - O(n + d)\nfunc pairNumbersMemoized(sum: Int) -> (Int, Int) {\n    \n\tvar addends = Set\u003CInt>()\n    \n\tfor a in sequence {\n    \t\tlet diff = sum - a\n   \t \n    \tif addends.contains(diff) { \u002F\u002FO(1) - constant time lookup\n     \t\t   \treturn (a, diff)\n    \t\t}\n    \t\t\u002F\u002Fstore previously seen value\n    \t\telse {\n        \t\taddends.insert(a)\n    \t\t}\n      }\n    \n\treturn (0, 0)\n }\n",{"_key":252,"_type":65,"children":253,"markDefs":258,"style":85},"f48bd20538fe",[254],{"_key":255,"_type":69,"marks":256,"text":257},"f48bd20538fe0",[],"Using a memoized approach, we've improved the algorithm's average run time efficiency to O(n + d) by adding previously seen values to a set collection object. Those familiar with hash-based structures will know that item insert and retrieval occurs in O(1) - constant time. This further streamlines the solution, as the set is designed to retrieve values in an optimized way regardless of size.",[],{"_key":260,"_type":65,"children":261,"markDefs":266,"style":267},"08ea4b9d3912",[262],{"_key":263,"_type":69,"marks":264,"text":265},"08ea4b9d39120",[],"The Fibonacci sequence",[],"h3",{"_key":269,"_type":65,"children":270,"markDefs":275,"style":85},"3b9c0f7b3ecc",[271],{"_key":272,"_type":69,"marks":273,"text":274},"3b9c0f7b3ecc0",[],"When learning various programming techniques, one topic that comes to mind is recursion. Recursive solutions work by having a model that refers to itself. As such, recursive techniques are implemented through algorithms or data structures. A well-known example of recursion can be seen with the Fibonacci sequence—a numerical sequence made by adding the two preceding numbers (0, 1, 1, 2, 3, 5, 8, 13, 21, etc):",[],{"_key":277,"_type":141,"code":278,"markDefs":12},"33126ef245ea","public func fibRec(_ n: Int) -> Int {\n    \tif n \u003C 2 {\n        \treturn n\n    \t} else {\n        \treturn fibRec(n-1) + fibRec(n-2)\n    \t}\n }\n",{"_key":280,"_type":65,"children":281,"markDefs":286,"style":85},"d5f5617c29ed",[282],{"_key":283,"_type":69,"marks":284,"text":285},"d5f5617c29ed0",[],"When examined, our code is error-free and works as expected. However, notice a few things about the performance of the algorithm:",[],{"_key":288,"_type":65,"children":289,"markDefs":302,"style":85},"66de6ee67a21",[290,294,298],{"_key":291,"_type":69,"marks":292,"text":293},"66de6ee67a210",[105],"Positions (n)",{"_key":295,"_type":69,"marks":296,"text":297},"66de6ee67a211",[105,141],"fibRec()",{"_key":299,"_type":69,"marks":300,"text":301},"66de6ee67a212",[105]," - Number of times called214510109151219",[],{"_key":304,"_type":65,"children":305,"markDefs":310,"style":85},"f4330fbf30d4",[306],{"_key":307,"_type":69,"marks":308,"text":309},"f4330fbf30d40",[],"As shown, there's a significant increase in the number of times our function is called. Similar to our previous example, the algorithm's performance decreases exponentially based on the input size. This occurs because the operation does not store previously calculated values. Without access to stored variables, the only way we can obtain the required (preceding) values is through recursion. Assuming this code is used in a production setting, the function could introduce bugs or performance errors. Let's refactor the code to support a memoized approach:",[],{"_key":312,"_type":141,"code":313,"markDefs":12},"ae39d9472117","func fibMemoizedPosition(_ n: Int) -> Int {\n\n    \tvar sequence: Array\u003CInt> = [0, 1]\n    \tvar results: Int = 0\n    \tvar i: Int = sequence.count\n   \t \n    \t\u002F\u002Ftrivial case\n    \tguard n > i else {\n        \treturn n\n    \t}\n   \t \n    \t\u002F\u002Fall other cases..\n    \twhile i \u003C= n {\n        \tresults = sequence[i - 1] + sequence[i - 2]\n        \tsequence.append(results)\n        \ti += 1\n    \t}\n   \t \n    \treturn results\n}\n",{"_key":315,"_type":65,"children":316,"markDefs":321,"style":85},"d4312c329f03",[317],{"_key":318,"_type":69,"marks":319,"text":320},"d4312c329f030",[],"This revised solution now supports memoization through the use of stored variables. Notice how the refactored code no longer requires a recursive technique. The two most previous values are added to a result, which is appended to the main array sequence. Even though the algorithm's performance still depends on the sequence size, our revisions have increased algorithmic efficiency to O(n) - linear time. In addition, our iterative solution should be easier to revise, test and debug since a single function is added to the call stack, thus reducing complexities with memory management and object scope.",[],{"_key":323,"_type":65,"children":324,"markDefs":329,"style":94},"d170e61f99ce",[325],{"_key":326,"_type":69,"marks":327,"text":328},"d170e61f99ce0",[],"Conclusion",[],{"_key":331,"_type":65,"children":332,"markDefs":337,"style":85},"9be674ea3d67",[333],{"_key":334,"_type":69,"marks":335,"text":336},"9be674ea3d670",[],"We've learned that dynamic programming isn't a specific design pattern as it is a way of thinking. Its goal is to create a solution to preserve previously seen values to increase time efficiency. While examples include basic algorithms, dynamic programming provides a foundation in almost all programs. This includes the use of simple variables and complex data structures.",[],true,"2022\u002F01\u002F31","Dynamic programming isn't about design patterns; it's a way of thinking that breaks down a problem into individual components. ",{"_type":53,"asset":342},{"_ref":343,"_type":56},"image-7482240dcf294374dcdc017e05110da9547582ad-2400x1260-jpg",{"code":345,"language":346},"\u003C!-- wp:paragraph -->\n\u003Cp>If you've been programming for long enough, you've probably heard the term dynamic programming. Often a key subject in \u003Ca href=\"https:\u002F\u002Fwww.waynewbishop.com\u002Fcomputer-science-interview-questions\">technical interviews\u003C\u002Fa>, the idea will also come up in design review meetings or regular interactions with fellow developers. This essay will examine what dynamic programming is and why you would use it. I'll be illustrating this concept with&nbsp; specific code examples in Swift, but the concepts I introduce can be applied to your language of choice. Let's begin!&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-a-way-of-thinking\">A way of thinking\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Unlike specific coding syntax or design patterns, dynamic programming isn't a particular algorithm but a \u003Cstrong>way of thinking\u003C\u002Fstrong>. Therefore, the technique takes many forms when it comes to implementation.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The main idea of \u003Ca href=\"https:\u002F\u002Fwww.waynewbishop.com\u002Fdynamic-programming-problems\">dynamic programming\u003C\u002Fa> is to consider a significant problem and break it into smaller, individualized components. When it comes to implementation, optimal techniques rely on data storage and reuse to increase algorithm efficiency. As we'll see, many questions in software development are solved using various forms of dynamic programming. The trick is recognizing when optimal solutions can be devised using a simple variable or require a sophisticated data structure or algorithm.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>For example, code variables can be considered an elementary form of dynamic programming. As we know, a variable's purpose is to reserve a specific place in memory for a value to be recalled later.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u002F\u002Fnon-memoized function\nfunc addNumbers(lhs: Int, rhs: Int) -&gt; Int {\n   return lhs + rhs\n}\n\n\u002F\u002Fmemoized function\nfunc addNumbersMemo(lhs: Int, rhs: Int) -&gt; Int {\n   let result: Int = lhs + rhs\n     return result\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>While \u003Ccode>addNumbersMemo\u003C\u002Fcode> above does provide a simple introduction, the goal of a dynamic programming solution is to preserve previously seen values because the alternative could either be inefficient or could prevent you from answering the question. This design technique is known as \u003Cstrong>memoization\u003C\u002Fstrong>.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-code-challenge-pair-of-numbers\">Code challenge—Pair of numbers\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Over the years, I've had the chance to conduct \u003Ca href=\"https:\u002F\u002Fwww.waynewbishop.com\u002Fios-interview\u002Fcslab\">mock interviews\u003C\u002Fa> with dozens of developers preparing for interviews at top companies like Apple, Facebook, and Amazon. Most of us would be happy to skip the realities of the dreaded whiteboard or take-home coding project. However, the fact is that many of these brain-teaser questions are designed to test for a basic understanding of computer science fundamentals. For example, consider the following:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u002F*\nIn a technical interview, you've been given an array of numbers and you need to find a pair of numbers that are equal to the given target value. Numbers can be either positive, negative, or both. Can you design an algorithm that works in O(n)—linear time or greater?\n\nlet sequence = &#91;8, 10, 2, 9, 7, 5]\nlet results = pairValues(sum: 11) = \u002F\u002Freturns (9, 2)\n*\u002F\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>As developers, we know there are usually multiple ways to arrive at a solution. In this case, the goal is knowing which numbers should be paired to achieve the expected result. As people, it's easy for us to quickly scan the sequence of numbers and promptly come up with the pair of 9 and 2. However, an algorithm will need to either check and compare each value in the sequence or develop a more streamlined solution to help us find the values we are seeking. Let's review both techniques.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-a-brute-force-approach\">A brute force approach\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Our first approach involves looking at the first value, then reviewing each subsequent value to determine if it will provide the \u003Cstrong>difference\u003C\u002Fstrong> needed to solve the question. For example, once our algorithm checks the value of the first array item, 8, it will then scan the remaining values for 3 (e.g., 11 - 8 = 3). However, we can see the value of 3 doesn't exist, so the algorithm will repeat the same process for the next value (in our case, 10) until it finds a successful matching pair. Without going into the details of big-O notation, we can assume this type of solution would have an average runtime of O(n ^ 2)time or greater, mainly because our algorithm works by comparing each value with every other value. In code, this can be represented as follows:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>let sequence = &#91;8, 10, 2, 9, 7, 5]\n\n\u002F\u002Fnon-memoized version - O(n ^ 2)\nfunc pairNumbers(sum: Int) -&gt; (Int, Int) {\n    \n\tfor a in sequence {\n    \t\tlet diff = sum - a\n   \t \n    \t\tfor b in sequence {\n        \t\tif (b != a) &amp;&amp; (b == diff) {\n            \t\treturn (a, b)\n        \t\t}\n    \t\t}\n\t}    \n\treturn (0, 0)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-a-memoized-approach\">A memoized approach\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Next, let's try a different approach using the idea of memoization. Before implementing our code, we can brainstorm how storing previously seen values will help streamline the process. While using a standard array is feasible, a set collection object (also referred to as a hash table or hash map) could provide an optimized solution.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u002F\u002Fmemoized version - O(n + d)\nfunc pairNumbersMemoized(sum: Int) -&gt; (Int, Int) {\n    \n\tvar addends = Set&lt;Int&gt;()\n    \n\tfor a in sequence {\n    \t\tlet diff = sum - a\n   \t \n    \tif addends.contains(diff) { \u002F\u002FO(1) - constant time lookup\n     \t\t   \treturn (a, diff)\n    \t\t}\n    \t\t\u002F\u002Fstore previously seen value\n    \t\telse {\n        \t\taddends.insert(a)\n    \t\t}\n      }\n    \n\treturn (0, 0)\n }\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Using a memoized approach, we've improved the algorithm's average run time efficiency to O(n + d) by adding previously seen values to a set collection object. Those familiar with hash-based structures will know that item insert and retrieval occurs in O(1) - constant time. This further streamlines the solution, as the set is designed to retrieve values in an optimized way regardless of size.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"the-fibonacci-sequence\">The Fibonacci sequence\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When learning various programming techniques, one topic that comes to mind is recursion. Recursive solutions work by having a model that refers to itself. As such, recursive techniques are implemented through algorithms or data structures. A well-known example of recursion can be seen with the Fibonacci sequence—a numerical sequence made by adding the two preceding numbers (0, 1, 1, 2, 3, 5, 8, 13, 21, etc):\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>public func fibRec(_ n: Int) -&gt; Int {\n    \tif n &lt; 2 {\n        \treturn n\n    \t} else {\n        \treturn fibRec(n-1) + fibRec(n-2)\n    \t}\n }\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When examined, our code is error-free and works as expected. However, notice a few things about the performance of the algorithm:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:table -->\n\u003Cfigure class=\"wp-block-table\">\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cstrong>Positions (n)\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>\u003Ccode>fibRec()\u003C\u002Fcode> - Number of times called\u003C\u002Fstrong>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>2\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>1\u003C\u002Fstrong>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>4\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>5\u003C\u002Fstrong>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>10\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>109\u003C\u002Fstrong>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Cstrong>15\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>\u003Cstrong>1219\u003C\u002Fstrong>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:table -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>As shown, there's a significant increase in the number of times our function is called. Similar to our previous example, the algorithm's performance decreases exponentially based on the input size. This occurs because the operation does not store previously calculated values. Without access to stored variables, the only way we can obtain the required (preceding) values is through recursion. Assuming this code is used in a production setting, the function could introduce bugs or performance errors. Let's refactor the code to support a memoized approach:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>func fibMemoizedPosition(_ n: Int) -&gt; Int {\n\n    \tvar sequence: Array&lt;Int&gt; = &#91;0, 1]\n    \tvar results: Int = 0\n    \tvar i: Int = sequence.count\n   \t \n    \t\u002F\u002Ftrivial case\n    \tguard n &gt; i else {\n        \treturn n\n    \t}\n   \t \n    \t\u002F\u002Fall other cases..\n    \twhile i &lt;= n {\n        \tresults = sequence&#91;i - 1] + sequence&#91;i - 2]\n        \tsequence.append(results)\n        \ti += 1\n    \t}\n   \t \n    \treturn results\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>This revised solution now supports memoization through the use of stored variables. Notice how the refactored code no longer requires a recursive technique. The two most previous values are added to a result, which is appended to the main array sequence. Even though the algorithm's performance still depends on the sequence size, our revisions have increased algorithmic efficiency to O(n) - linear time. In addition, our iterative solution should be easier to revise, test and debug since a single function is added to the call stack, thus reducing complexities with memory management and object scope.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"conclusion\">Conclusion\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>We've learned that dynamic programming isn't a specific design pattern as it is a way of thinking. Its goal is to create a solution to preserve previously seen values to increase time efficiency. While examples include basic algorithms, dynamic programming provides a foundation in almost all programs. This includes the use of simple variables and complex data structures.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->","html","2022-01-31T14:48:08.000Z",{"current":349},"the-complete-beginners-guide-to-dynamic-programming",[351,359,363,368],{"_createdAt":352,"_id":353,"_rev":354,"_type":355,"_updatedAt":352,"slug":356,"title":358},"2023-05-23T16:43:21Z","wp-tagcat-code-for-a-living","9HpbCsT2tq0xwozQfkc4ih","blogTag",{"current":357},"code-for-a-living","Code for a Living",{"_createdAt":352,"_id":360,"_rev":354,"_type":355,"_updatedAt":352,"slug":361,"title":123},"wp-tagcat-dynamic-programming",{"current":362},"dynamic-programming",{"_createdAt":352,"_id":364,"_rev":354,"_type":355,"_updatedAt":352,"slug":365,"title":367},"wp-tagcat-software-development",{"current":366},"software-development","software development",{"_createdAt":369,"_id":370,"_rev":371,"_system":372,"_type":355,"_updatedAt":375,"description":376,"slug":385,"title":387},"2025-04-24T16:28:57Z","797b8797-6e65-4723-b53f-8bc005305384","IpfPEqg1c3Byvj9RrB3Xaj",{"base":373},{"id":370,"rev":374},"oc42Nphz1oZNOg9ttSv7Tn","2026-05-07T14:43:30Z",[377],{"_key":378,"_type":65,"children":379,"markDefs":384,"style":85},"bb32f75814b4",[380],{"_key":381,"_type":69,"marks":382,"text":383},"dbcf27ef29b3",[],"Community-generated articles submitted for your reading pleasure. If you’re interested in seeing your work here, log in with your Stack Overflow account and click the link below. Articles will be licensed under a CC BY-SA 4.0 grant. ",[],{"_type":10,"current":386},"contributed","The Heap","The complete beginners guide to dynamic programming ",[390,396,402,408],{"_id":391,"publishedAt":392,"slug":393,"sponsored":12,"title":395},"76c9771b-34e6-4d98-8641-ecefc711f0ef","2026-07-06T15:23:34.559Z",{"_type":10,"current":394},"when-the-sensor-starts-thinking-snortml-agentic-ai-and-the-evolving-architecture-of-intrusion-detection","When the sensor starts thinking: SnortML, agentic AI, and the evolving architecture of intrusion detection",{"_id":397,"publishedAt":398,"slug":399,"sponsored":12,"title":401},"28e560af-f0aa-4d46-bd90-f435ad604aa7","2026-06-26T14:00:27.102Z",{"_type":10,"current":400},"paging-charity-how-can-engineering-leaders-avoid-becoming-bond-villains","Paging Charity! How can engineering leaders avoid becoming Bond villains?",{"_id":403,"publishedAt":404,"slug":405,"sponsored":12,"title":407},"4b22c2a3-3779-4966-93eb-5230391dbdce","2026-06-23T14:08:58.595Z",{"_type":10,"current":406},"your-ai-shipped-a-backend-that-boots-that-is-the-whole-problem","Your AI shipped a backend that boots. That is the whole problem.",{"_id":409,"publishedAt":410,"slug":411,"sponsored":12,"title":413},"5cf362e1-fe7b-45af-b69c-914731c6a052","2026-06-23T14:00:00.000Z",{"_type":10,"current":412},"the-2026-developer-survey-is-now-open-for-human-developers-only","The 2026 Developer Survey is now open (for human developers only)!",{"data":415,"sourceMap":-1},{"count":416,"lastTimestamp":417},16,"2025-01-21T21:57:21Z"]