eolas/neuron/d0ed26d0-cdc8-4643-8c09-445408195f9b/.neuron/output/Algorithmic_complexity.html
2024-10-20 19:00:04 +01:00

84 lines
No EOL
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type" /><meta content="width=device-width, initial-scale=1" name="viewport" /><!--replace-start-0--><!--replace-start-5--><!--replace-start-8--><title>Algorithmic complexity - My Zettelkasten</title><!--replace-end-8--><!--replace-end-5--><!--replace-end-0--><link href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.7/dist/semantic.min.css" rel="stylesheet" /><link href="https://fonts.googleapis.com/css?family=Merriweather|Libre+Franklin|Roboto+Mono&amp;display=swap" rel="stylesheet" /><!--replace-start-1--><!--replace-start-4--><!--replace-start-7--><link href="https://raw.githubusercontent.com/srid/neuron/master/assets/neuron.svg" rel="icon" /><meta content="Screenshot_2021-05-11_at_18.55.23.png Summary of the main classes of algorithmic complexity" name="description" /><meta content="Algorithmic complexity" property="og:title" /><meta content="My Zettelkasten" property="og:site_name" /><meta content="article" property="og:type" /><meta content="Algorithmic_complexity" property="neuron:zettel-id" /><meta content="Algorithmic_complexity" property="neuron:zettel-slug" /><meta content="algorithms" property="neuron:zettel-tag" /><script type="application/ld+json">[]</script><style type="text/css">body{background-color:#eeeeee !important;font-family:"Libre Franklin", serif !important}body .ui.container{font-family:"Libre Franklin", serif !important}body h1, h2, h3, h4, h5, h6, .ui.header, .headerFont{font-family:"Merriweather", sans-serif !important}body code, pre, tt, .monoFont{font-family:"Roboto Mono","SFMono-Regular","Menlo","Monaco","Consolas","Liberation Mono","Courier New", monospace !important}body div.z-index p.info{color:#808080}body div.z-index ul{list-style-type:square;padding-left:1.5em}body div.z-index .uplinks{margin-left:0.29999em}body .zettel-content h1#title-h1{background-color:rgba(33,133,208,0.1)}body nav.bottomPane{background-color:rgba(33,133,208,2.0e-2)}body div#footnotes{border-top-color:#2185d0}body p{line-height:150%}body img{max-width:100%}body .deemphasized{font-size:0.94999em}body .deemphasized:hover{opacity:1}body .deemphasized:not(:hover){opacity:0.69999}body .deemphasized:not(:hover) a{color:#808080 !important}body div.container.universe{padding-top:1em}body div.zettel-view ul{padding-left:1.5em;list-style-type:square}body div.zettel-view .pandoc .highlight{background-color:#ffff00}body div.zettel-view .pandoc .ui.disabled.fitted.checkbox{margin-right:0.29999em;vertical-align:middle}body div.zettel-view .zettel-content .metadata{margin-top:1em}body div.zettel-view .zettel-content .metadata div.date{text-align:center;color:#808080}body div.zettel-view .zettel-content h1{padding-top:0.2em;padding-bottom:0.2em;text-align:center}body div.zettel-view .zettel-content h2{border-bottom:solid 1px #4682b4;margin-bottom:0.5em}body div.zettel-view .zettel-content h3{margin:0px 0px 0.4em 0px}body div.zettel-view .zettel-content h4{opacity:0.8}body div.zettel-view .zettel-content div#footnotes{margin-top:4em;border-top-style:groove;border-top-width:2px;font-size:0.9em}body div.zettel-view .zettel-content div#footnotes ol > li > p:only-of-type{display:inline;margin-right:0.5em}body div.zettel-view .zettel-content aside.footnote-inline{width:30%;padding-left:15px;margin-left:15px;float:right;background-color:#d3d3d3}body div.zettel-view .zettel-content .overflows{overflow:auto}body div.zettel-view .zettel-content code{margin:auto auto auto auto;font-size:100%}body div.zettel-view .zettel-content p code, li code, ol code{padding:0.2em 0.2em 0.2em 0.2em;background-color:#f5f2f0}body div.zettel-view .zettel-content pre{overflow:auto}body div.zettel-view .zettel-content dl dt{font-weight:bold}body div.zettel-view .zettel-content blockquote{background-color:#f9f9f9;border-left:solid 10px #cccccc;margin:1.5em 0px 1.5em 0px;padding:0.5em 10px 0.5em 10px}body div.zettel-view .zettel-content.raw{background-color:#dddddd}body .ui.label.zettel-tag{color:#000000}body .ui.label.zettel-tag a{color:#000000}body nav.bottomPane ul.backlinks > li{padding-bottom:0.4em;list-style-type:disc}body nav.bottomPane ul.context-list > li{list-style-type:lower-roman}body .footer-version img{-webkit-filter:grayscale(100%);-moz-filter:grayscale(100%);-ms-filter:grayscale(100%);-o-filter:grayscale(100%);filter:grayscale(100%)}body .footer-version img:hover{-webkit-filter:grayscale(0%);-moz-filter:grayscale(0%);-ms-filter:grayscale(0%);-o-filter:grayscale(0%);filter:grayscale(0%)}body .footer-version, .footer-version a, .footer-version a:visited{color:#808080}body .footer-version a{font-weight:bold}body .footer-version{margin-top:1em !important;font-size:0.69999em}@media only screen and (max-width: 768px){body div#zettel-container{margin-left:0.4em !important;margin-right:0.4em !important}}body span.zettel-link-container span.zettel-link a{color:#2185d0;font-weight:bold;text-decoration:none}body span.zettel-link-container span.zettel-link a:hover{background-color:rgba(33,133,208,0.1)}body span.zettel-link-container span.extra{color:auto}body span.zettel-link-container.errors{border:solid 1px #ff0000}body span.zettel-link-container.errors span.zettel-link a:hover{text-decoration:none !important;cursor:not-allowed}body [data-tooltip]:after{font-size:0.69999em}body div.tag-tree div.node{font-weight:bold}body div.tag-tree div.node a.inactive{color:#555555}body .tree.flipped{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}body .tree{overflow:auto}body .tree ul.root{padding-top:0px;margin-top:0px}body .tree ul{position:relative;padding:1em 0px 0px 0px;white-space:nowrap;margin:0px auto 0px auto;text-align:center}body .tree ul::after{content:"";display:table;clear:both}body .tree ul:last-child{padding-bottom:0.1em}body .tree li{display:inline-block;vertical-align:top;text-align:center;list-style-type:none;position:relative;padding:1em 0.5em 0em 0.5em}body .tree li::before{content:"";position:absolute;top:0px;right:50%;border-top:solid 2px #cccccc;width:50%;height:1.19999em}body .tree li::after{content:"";position:absolute;top:0px;right:50%;border-top:solid 2px #cccccc;width:50%;height:1.19999em}body .tree li::after{right:auto;left:50%;border-left:solid 2px #cccccc}body .tree li:only-child{padding-top:0em}body .tree li:only-child::after{display:none}body .tree li:only-child::before{display:none}body .tree li:first-child::before{border-style:none;border-width:0px}body .tree li:first-child::after{border-radius:5px 0px 0px 0px}body .tree li:last-child::after{border-style:none;border-width:0px}body .tree li:last-child::before{border-right:solid 2px #cccccc;border-radius:0px 5px 0px 0px}body .tree ul ul::before{content:"";position:absolute;top:0px;left:50%;border-left:solid 2px #cccccc;width:0px;height:1.19999em}body .tree li div.forest-link{border:solid 2px #cccccc;padding:0.2em 0.29999em 0.2em 0.29999em;text-decoration:none;display:inline-block;border-radius:5px 5px 5px 5px;color:#333333;position:relative;top:2px}body .tree.flipped li div.forest-link{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}</style><script
async=""
id="MathJax-script"
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
></script>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/themes/prism.min.css"
rel="stylesheet"
/><link rel="preconnect" href="https://fonts.googleapis.com" /><link
rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin
/><link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=IBM+Plex+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=IBM+Plex+Serif:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
rel="stylesheet"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/components/prism-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/autoloader/prism-autoloader.min.js"></script>
<style>
body .ui.container,
body ul {
font-family: "IBM Plex Sans" !important;
}
body blockquote {
border-left-width: 3px !important;
font-style: italic;
}
.headerFont,
.ui.header,
body h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "IBM Plex Sans Condensed" !important;
}
body p {
line-height: 1.4;
}
.monoFont,
body code,
pre,
tt {
font-family: "IBM Plex Mono" !important;
font-size: 12px !important;
line-height: 1.4 !important;
}
</style>
<!--replace-end-7--><!--replace-end-4--><!--replace-end-1--></head><body><div class="ui fluid container universe"><!--replace-start-2--><!--replace-start-3--><!--replace-start-6--><div class="ui text container" id="zettel-container" style="position: relative"><div class="zettel-view"><article class="ui raised attached segment zettel-content"><div class="pandoc"><h1 id="title-h1">Algorithmic complexity</h1><p><img alt="Screenshot_2021-05-11_at_18.55.23.png" src="/static/Screenshot_2021-05-11_at_18.55.23.png" /> <em>Summary of the main classes of algorithmic complexity</em></p><h2 id="distinguish-algorithms-from-programs">Distinguish algorithms from programs</h2><p>Test commit Algorithms are general sets of instructions that take data in one state, follow a prescribed series of steps and return data in another state. Programs are a specific application of one or more algorithms to achieve an outcome in a specific context. With algorithms, the actual detail of the steps is mostly abstracted and it is irrelevant to what end the algorithm is being put. For instance you may create a program that returns addresses from a database using a postcode. It is irrelevant to the efficiency or value of the algorithm whether or not you are looking up postcodes or some other form of alphanumeric string.</p><h2 id="algorithmic-efficiency">Algorithmic efficiency</h2><p>Algorithms can be classified based on their efficiency. Efficiency is function of the runtime speed. However this doesnt always mean that the fastest algorithms are best.</p><p>If we are landing the Curiosity Rover on Mars we may choose an algorithm that is slower on average for a guarantee that it will never take longer than we find acceptable. In other cases for example a video game, we may choose an algorithm that keeps the average time down, even if this occasionally leads to processes that need to be aborted because they take too long.</p><p>We need a generalised measure of efficiency to compare algorithms, across variant hardware. We cant simply use the number of steps, since some steps will be quicker to complete than others in the course of the overall algorithm and may take longer on different machines. Moreover the same algorithm could run at different speeds on the same machine, depending on its internal state at the given time that it ran. So we use the following: <strong>the number of steps required relative to the input.</strong></p><blockquote><p>Two given computers may differ in how quickly they can run an algorithm depending on clock speed, available memory and so forth. They will however tend to require approximately the same number of instructions and we can measure the rate at which the number of instructions increases with the problem size.</p></blockquote><p>This is what <strong>asymptotic runtime</strong> means: the rate at which the runtime of an algorithm grows compared to the size of its input. For precision and accuracy we use the worst case scenario as the benchmark.</p><p>So: the efficiency of algorithm <em>A</em> can be judged relative to the efficiency of algorithm <em>B</em> based on the rate at which the runtime of <em>A</em> grows compared to its input, compared to the same property in <em>B</em>, assuming the worst possible performance.</p><p>From now on we will use the word input to denote the data that the algorithm receives (in most cases we will envision this as an array containing a certain data type) and execution to denote the computation that is applied by the algorithm to each item of the data input. Rephrasing the above with these terms we can say that algorithmic efficiency is a measure that describes the rate at which the execution time of an algorithm increases relative to the size of its input.</p><p>We will find that for the runtime of some algorithms, the size of the input does not change the execution time. In these cases, the runtime is proportional to the input quantity. In this case, regardless of whether the input is an array of one hundred elements or an array of ten elements, the amount of work that is executed on each element is the same.</p><p>For other cases, this will not hold true. We will find that there is a relationship between input size and execution time such that the length of the input affects the amount of work that needs to be performed on each item at execution.</p><h2 id="linear-time">Linear time</h2><p>Lets start with linear time, which is the easiest runtime to grasp.</p><p>We need an example to make this tangible and show how an algorithms runtime changes compared to the size of its input. Lets take a simple function that takes a sequence of integers and returns their sum:</p><pre><code class="js language-js">function findSum(arr){
let total = 0;
for (let i = 0; i &lt; arr.length; i++){
total = total += arr[i];
)
return total
}</code></pre><p>The input of this function is an array of integers. It returns their sum as the output. Lets say that it takes 1ms for the function to sum an array of two integers.</p><p>If we passed in an array of four integers, how would this change the runtime? The answer is that, providing that the time it takes to sum two integers doesnt change, it would take twice as long.</p><p>As the time it takes to execute <code>findSum</code> doesnt change, we can say confidently that the runtime is as long as the number of integers we pass in.</p><p>A more general way to say this is that the runtime is equal to size of the input. For algorithms of the class of which <code>findSum</code> is a member: <strong>the total runtime is proportional to the number of items to be processed</strong>.</p><h2 id="introducing-asymptotic-notation">Introducing asymptotic notation</h2><p>If we say that it takes 1ms for two integers to be summed, this gives us the following data set:</p><table class="ui table"><thead><tr><th>Length of input</th><th>Runtime</th></tr></thead><tbody><tr><td>2</td><td>2</td></tr><tr><td>3</td><td>3</td></tr><tr><td>4</td><td>4</td></tr><tr><td>5</td><td>5</td></tr></tbody></table><p>If we plotted this as a graph it is clear that this is equivalent to a linear distribution:<img alt="lin.svg" src="/static/lin.svg" /></p><p>Algorithms which display this distribution are therefore called <strong>linear algorithms</strong>.</p><p>The crucial point is that the amount of time it takes to sum the integers does not increase as the algorithm proceeds and the input size grows. This time remains the same. If it did increase, we would have a fluctuating curve on the graph. This aspect remains constant, only the instructions increase. This is why we have a nice steadily-advancing distribution in the graph.</p><p>We can now introduce notation to formalise the algorithmic properties we have been discussing.</p><h2 id="big-o-notation">Big O notation</h2><p>To express linear time algorithms formally, we say that:</p><blockquote><p>it takes some constant amount of time (<span class="math inline">\(C\)</span>) to sum one integer and n times as long to sum n integers</p></blockquote><p>Here the constant is the time for each execution to run and n is the length of the input. Thus the complexity is equal to that time multiplied by the input.</p><p>The algebraic expression of this is <span class="math inline">\(cn\)</span> : the constant multiplied by the length of the input. In algorithmic notation, the reference to the constant is always removed. Instead we just use n and combine it with a big O which stands for order of complexity. Likewise, if we have an array of four integers being passed to <code>findSum</code> we could technically express it as O(4n), but we dont because we are interested in the general case not the specific details of the runtime. So a linear algorithm is expressed algebraically as <span class="math inline">\(O(n)\)</span> which is read as “oh of n” and means</p><blockquote><p><span class="math inline">\(O(n)\)</span> = with an order of complexity equal to (some constant) multiplied by n</p></blockquote><p>Applied, this means an input of length 6 (<span class="math inline">\(n\)</span>) where runtime is constant (<span class="math inline">\(c\)</span>) at 1ms has a total runtime of 6 x 1 = 6ms in total. Exactly the same as our table and graph. O n is just a mathematical way of saying <em>the runtime grows on the order of the size of the input.</em></p><blockquote><p>Its really important to remember that when we talk about the execution runtime being constant at 1ms, this is just an arbitrary placeholder. We are not really bothered about whether its 1ms or 100ms: constant in the mathematical sense doesnt mean a unit of time, it means unchanging. We are using 1ms to get traction on this concept but the fundamental point being expressed is that the size of the input doesnt affect the execution time across the length of the execution time.</p></blockquote><h2 id="constant-time">Constant time</h2><p>Constant time is another one of the main classes of algorithmic complexity. It is expressed as O(1). Here, we do away with n because with constant time we are only ever dealing with a single execution so we dont need a variable to express nth in a series or more than one. Constant time covers all singular processes, without iteration.</p><p>An example in practice would be printing <code>array[0]</code> . Regardless of the size of the array, it is only ever going to take one step, or constant times one. On a graph this is equivalent to a flat line along the time axis. Since it only happens for one instant, it doesnt persist over time or have multiple iterations.</p><h3 id="relation-to-linear-time">Relation to linear time</h3><p>If you think about it, there is a clear logical relationship between constant and linear time: because the execution time of a linear algorithm is constant, regardless of the size of n, each execution of O(n) is equal to O(1). Thus O(n) is simply O(1) writ large or iterated. At any given execution of an O(n) algorithm n is going to be equal to 1.</p><h2 id="quadratic-time">Quadratic time</h2><p>With the examples of constant and linear time, the total number of instructions doesnt change the amount of work that needs to be performed for each item, but this only covers one subset of algorithms. In cases other than O(1) and O(n), the length of the input <strong>can</strong> affect the amount of work that needs to be performed at execution. The most common example of this scenario is known as quadratic time, represented as <span class="math inline">\(O(n^2)\)</span>.</p><p>Lets start with an example.</p><pre><code class="js language-js">const letters = [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;];
function quadratic(arr) {
for (let i = 0; i &lt; arr.length; i++) {
for (let j = 0; j &lt; arr.length j++) {
console.log(arr[i]);
}
}
}
quadratic(letters);</code></pre><p>This function takes an array . The outer loop runs once for each element of the array that is passed to the function. For each iteration of the outer loop, the inner loop also runs once for each element of the array.</p><p>In the example this means that the following is output:</p><pre><code class="language-none">A A A B B B C C C (length: 9)</code></pre><p>Mathematically this means that n (the size of the input) grows at a rate of n2 or the input multiplied by itself. Our outer loop (<code>i</code>) is performing n iterations (just like in linear time) but our inner loop (<code>j</code>) is also performing n iterations, three <code>j</code>s for every one <code>i</code> . It is performing n iterations for every nth iteration of the outer loop. So runtime here is directly proportional to the squared size of the input data set. As the input array has a length of 3, and the inner array runs once for every element in the array, this is equal to 3 x 3 or 3 squared (9).</p><p>If the input had length 4, the runtime would be 16 or 4x4. For every execution of linear time (the outer loop) the inner loop runs as many times as is equal to the length of the input.</p><p>This is not a linear algorithm because as n grows the runtime increases as a factor of it. Therefore the runtime is not growing proportional to the size of the input, it is growing proportional to the size of the input squared.</p><p>Graphically this is represented with a curving lines as follows: <img alt="square.svg" src="/static/square.svg" /></p><p>We can clearly see that as n grows, the runtime gets steeper and more pronounced,</p><h2 id="logarithmic-time-log-n">Logarithmic time (log n)</h2><p>A logarithm is best understood as the inverse of exponentiation:</p><p><span class="math display">$$ \log \_{2}8 = 3 \leftrightarrow 2^3 = 8 $$</span></p><p>When we use log in the context of algorithms we are always using the binary number system so we omit the 2, we just say log.</p><blockquote><p>With base two logarithms, the logarithm of a number roughly measures the number of times you can divide that number by 2 before you get a value that is less than or equal to 1</p></blockquote><p>So applying this to the example of <span class="math inline">\(\log 8\)</span> , it is borne out as follows:</p><ul><li>8 / 2 = 4 — count: 1</li><li>4 / 2 = 2 — count: 2</li><li>2 / 2 = 1 — count: 3</li></ul><p>As we are now at 1, we cant divide any more, so <span class="math inline">\(\log 8\)</span> is equal to 3.</p><p>Obviously this doesnt work so neatly with odd numbers, so we approximate.</p><p>For example, with <span class="math inline">\(\log 25\)</span>:</p><ul><li><p>25 / 2 = 12.5 — count: 1</p></li><li><p>12.5 / 2 = 6.25 — count: 2</p></li><li><p>6.25 / 2 = 3.125 — count: 3</p></li><li><p>3.125 / 2 = 1.5625 — count: 4</p></li><li><p>1.5625 / 2 = 0.78125</p><p>Now we are lower than 1 so we have to stop. We can only say that the answer to <span class="math inline">\(\log 25\)</span> is somewhere between 4 and 5.</p><p>The exact answer is <span class="math inline">\(\log 25 \approx 4.64\)</span></p></li></ul><p>Back to algorithms: <span class="math inline">\(O(\log n)\)</span> is a really good complexity to have. It is close to O(1) and in between O(1) and O(n). Represented graphically, it starts of with a slight increase in runtime but then quickly levels off:</p><p><img alt="Screenshot_2021-05-11_at_18.51.02.png" src="/static/Screenshot_2021-05-11_at_18.51.02.png" /></p><p>Many sorting algorithms run in log n time, as does recursion.</p><h2 id="reducing-o-complexity-to-the-general-case">Reducing O complexity to the general case</h2><p>When we talk about big O we are looking for the most general case, slight deviations, additions or diminutions in n are not as important as the big picture. We are looking for the underlying logic and patterns that are summarised by the classes of O(1), O(n), O(n2) and others.</p><p>For example, with the following function:</p><pre><code class="js language-js">function sumAndAddTwo(arr) {
let total = 0;
for (let i = 0; i &lt; arr.length; i++) {
total += arr[i];
}
total = total += 2;
}</code></pre><p>The formal representation of the above complexity would be O(n) + O(1). But its easier just to say O(n), since the O(1) that comes from adding two to the result of the loop, makes a marginal difference overall.</p><p>Similarly, with the following function:</p><pre><code class="js language-js">function processSomeIntegers(integers){
let sum, product = 0;
integers.forEach(function(int){
return sum += int;
}
integers.forEach(function(int){
return product *= int;
}
console.log(`The sum is ${sum} and the product is ${product}`);
}</code></pre><p>It might appear to be more complex than the earlier summing function but it isnt really. We have one array (<code>integers</code> ) and two loops. Each loop is of O(n) complexity and does a constant amount of work. If we add O(n) and O(n) we still have O(n), not O(2n). The constant isnt changed in any way by the fact that we are looping twice through the array in separate processes, it just doubles the length of n. So rather than formalising this as O(n) + O(n), we just reduce it to O(n).</p><p>When seeking to simplify algorithms to their most general level of complexity, we should keep in mind the following shorthands:</p><ul><li>Arithmetic operations always take constant time</li><li>Variable assignment always takes constant time</li><li>Accessing an element in an array by index or an object value by key is always constant</li><li>in a loop the complexity is the length of the loop times the complexity of whatever happens inside of the loop</li></ul><p>With this in mind we can break down the <code>findSum</code> function like so:</p><p><img alt="breakdown.svg" src="/static/breakdown.svg" /></p><p>This gives us:</p><p><span class="math display">$$ O(1) + O(1) + O(n) $$</span></p><p>Which, as noted above can just be reduced to O(n).</p><h2 id="space-complexity">Space complexity</h2><p>So far we have talked about time complexity only: how the runtime changes relative to the size of the input. With space complexity, we are interested in how much memory (conceived as an abstract spatial quantity corresponding to the machines hardware) is required by the algorithm. We can use Big O notation for space complexity as well as time complexity.</p><p>Space complexity in this sense is called auxiliary space complexity. This means the space that the algorithm itself takes up, independent of the the size of the inputs. We are not focusing on the space that each input item takes up, only the overall space of the algorithm.</p><p>Again there are some rules of thumb:</p><ul><li>Booleans, <code>undefined</code>, and <code>null</code> take up constant space</li><li>Strings require O(n) space, where n is the sting length</li><li>Reference types take up O(n): an array of length 4 takes up twice as much space as an array of length 2</li></ul><p>So with space complexity we are not really interested in how many times the function executes, if it is a loop. We are looking to where data is stored: how many variables are initialised, how many items there are in the array.</p></div></article><nav class="ui attached segment deemphasized bottomPane" id="neuron-tags-pane"><div><span class="ui basic label zettel-tag" title="Tag">algorithms</span></div></nav><nav class="ui bottom attached icon compact inverted menu blue" id="neuron-nav-bar"><!--replace-start-9--><!--replace-end-9--><a class="right item" href="impulse.html" title="Open Impulse"><i class="wave square icon"></i></a></nav></div></div><!--replace-end-6--><!--replace-end-3--><!--replace-end-2--><div class="ui center aligned container footer-version"><div class="ui tiny image"><a href="https://neuron.zettel.page"><img alt="logo" src="https://raw.githubusercontent.com/srid/neuron/master/assets/neuron.svg" title="Generated by Neuron 1.9.35.3" /></a></div></div></div></body></html>