{"id":194,"date":"2021-02-07T22:17:57","date_gmt":"2021-02-07T22:17:57","guid":{"rendered":"https:\/\/gnikesh.com\/?p=194"},"modified":"2021-03-05T19:29:08","modified_gmt":"2021-03-05T19:29:08","slug":"maximum-subsequence-sum-of-an-array","status":"publish","type":"post","link":"https:\/\/gnikesh.com\/index.php\/2021\/02\/07\/maximum-subsequence-sum-of-an-array\/","title":{"rendered":"Maximum Subsequence Sum of an Array"},"content":{"rendered":"\n<p>First, let&#8217;s define what a  maximum subsequence sum problem is.  Suppose we have an array [5, -3, 4, -7, 8, 7, 4, -1] then we would want to find a contiguous sequence that has the maximum sum. In this case, subsequence [8, 7, 4] has the maximum sum i.e. 19. It&#8217;s worth noting that if the array did not have any negative numbers, the subsequence with maximum sum would be simply the given array. And, for this problem, let&#8217;s consider if all elements are negative, the maximum sum would be 0. <\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Mathematically, if A is an array with <em>&#8216;n&#8217;<\/em> elements,  we could define the maximum subsequence sum of A as<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 53px;\"><span class=\"ql-right-eqno\"> (1) <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-cbe5ce459c520fb147ce7ded5293cc02_l3.png\" height=\"53\" width=\"231\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#101;&#113;&#117;&#97;&#116;&#105;&#111;&#110;&#42;&#125;&#92;&#109;&#97;&#120;&#92;&#123;&#92;&#115;&#117;&#109;&#95;&#123;&#107;&#61;&#105;&#125;&#94;&#123;&#106;&#45;&#49;&#125;&#65;&#92;&#108;&#101;&#102;&#116;&#91;&#107;&#92;&#114;&#105;&#103;&#104;&#116;&#93;&#124;&#92;&#58;&#48;&#92;&#108;&#101;&#32;&#105;&#92;&#108;&#101;&#32;&#106;&#92;&#108;&#101;&#32;&#110;&#92;&#125;&#92;&#101;&#110;&#100;&#123;&#101;&#113;&#117;&#97;&#116;&#105;&#111;&#110;&#42;&#125;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\n\n\n\n<p>Let&#8217;s solve this problem in few ways<\/p>\n\n\n\n<p><strong>1. A simple brute force approach to generate all subsequence sums and return the highest sum. <\/strong>Let&#8217;s see a code to implement definition (1) in python<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<pre class=\"wp-block-code\"><code>def max_subsequence_sum(A):\n    max_sum = 0\n    n = len(A)\n    for i in range(n):\n        for j in range(n):\n            curr_sum = 0\n            for k in range(i, j):\n                curr_sum += A&#91;k]\n            max_sum = max(max_sum, curr_sum)\n    return max_sum\n   <\/code><\/pre>\n<\/div><\/div>\n\n\n\n<p>When we run this function with [5, -3, 4, -7, 8, 7, 4, -1], it returns 19 which is a correct answer. If we look into the code, this function has 3 nested loops, and if the size of the array becomes very large, this function takes really long time to get the results. For this function, we have:<\/p>\n\n\n\n<p><span style=\"text-decoration: underline;\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-cf1105a6dabba9db2a65dfd035a85fc0_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#84;&#105;&#109;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#79;&#40;&#110;&#94;&#51;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"20\" width=\"202\" style=\"vertical-align: -5px;\"\/><br><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-493f4b9448f74238c1401e3f9b5a46c2_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#83;&#112;&#97;&#99;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#79;&#40;&#49;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"196\" style=\"vertical-align: -5px;\"\/><\/span><\/p>\n\n\n\n<p>So we definitely need to improve the time complexity of this function.<\/p>\n\n\n\n<p><strong>2. Removing unnecessary loops from our previous solution.<\/strong> Let&#8217;s see how we can optimize the above function by removing the second <em>for<\/em> loop. Python code would look something like<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def max_subsequence_sum(A):\n    max_sum = 0\n    n = len(A)\n    for i in range(n):\n            curr_sum = 0\n            for k in range(i, n):\n                curr_sum += A&#91;k]\n                max_sum = max(max_sum, curr_sum)\n    return max_sum<\/code><\/pre>\n\n\n\n<p>For this function, we would then have:<\/p>\n\n\n\n<p><span style=\"text-decoration: underline;\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-d7b93f73b14db776e3594bb722f0fb6f_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#84;&#105;&#109;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#79;&#40;&#110;&#94;&#50;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"20\" width=\"202\" style=\"vertical-align: -5px;\"\/><br><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-493f4b9448f74238c1401e3f9b5a46c2_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#83;&#112;&#97;&#99;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#79;&#40;&#49;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"196\" style=\"vertical-align: -5px;\"\/><\/span><\/p>\n\n\n\n<p>Can we do better? Let&#8217;s look at a top-down approach.<\/p>\n\n\n\n<p><strong>3. A Top-Down<\/strong> Solution. For a given array A with n number of elements i.e. A[0&#8230;n-1], we can represent the maximum subsequence sum of A as s<sub>n<\/sub>. And s<sub>n-1<\/sub> would then be A[0&#8230;n-2] for n &gt; 0. Then our overall maximum subsequence sum would be the maximum of s<sub>n-1<\/sub> and all of the sums of subsequences A[i&#8230;n-1] for 0 &lt;= i &lt;= n which we represent as t<sub>n<\/sub>.<\/p>\n\n\n\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 43px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-dbb31a3ee73956044063bfb594e5bf3d_l3.png\" height=\"43\" width=\"264\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#91;&#32;&#115;&#95;&#110;&#32;&#61;&#32;&#92;&#108;&#101;&#102;&#116;&#92;&#123;&#32;&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#114;&#114;&#97;&#121;&#125;&#123;&#99;&#99;&#125;&#32;&#48;&#32;&#38;&#32;&#105;&#102;&#32;&#92;&#113;&#117;&#97;&#100;&#32;&#110;&#32;&#61;&#32;&#48;&#32;&#92;&#92;&#32;&#109;&#97;&#120;&#40;&#115;&#95;&#123;&#110;&#45;&#49;&#125;&#44;&#32;&#116;&#95;&#110;&#41;&#32;&#38;&#32;&#105;&#102;&#32;&#92;&#113;&#117;&#97;&#100;&#32;&#110;&#32;&#62;&#32;&#48;&#32;&#92;&#101;&#110;&#100;&#123;&#97;&#114;&#114;&#97;&#121;&#125;&#32;&#92;&#114;&#105;&#103;&#104;&#116;&#46;&#32;&#92;&#93;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\n\n\n\n<p>And, this sum of <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-96c3035dc11c29c853f804bc31934ad0_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#116;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"14\" style=\"vertical-align: -3px;\"\/>, which we call maximum suffix sum will be defined as <\/p>\n\n\n\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 53px;\"><span class=\"ql-right-eqno\"> (2) <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-a634b6ba144da71d5989bcdb7eadce4d_l3.png\" height=\"53\" width=\"231\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#101;&#113;&#117;&#97;&#116;&#105;&#111;&#110;&#42;&#125;&#92;&#109;&#97;&#120;&#92;&#123;&#92;&#115;&#117;&#109;&#95;&#123;&#107;&#61;&#105;&#125;&#94;&#123;&#110;&#45;&#49;&#125;&#65;&#92;&#108;&#101;&#102;&#116;&#91;&#107;&#92;&#114;&#105;&#103;&#104;&#116;&#93;&#124;&#92;&#58;&#48;&#92;&#108;&#101;&#32;&#105;&#92;&#108;&#101;&#32;&#106;&#92;&#108;&#101;&#32;&#110;&#92;&#125;&#92;&#101;&#110;&#100;&#123;&#101;&#113;&#117;&#97;&#116;&#105;&#111;&#110;&#42;&#125;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\n\n\n\n<p>And we can calculate <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-96c3035dc11c29c853f804bc31934ad0_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#116;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"14\" style=\"vertical-align: -3px;\"\/> as<\/p>\n\n\n\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 19px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-8890718cbfa556665615145468b91d71_l3.png\" height=\"19\" width=\"223\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#91;&#32;&#116;&#95;&#110;&#32;&#61;&#32;&#109;&#97;&#120;&#40;&#48;&#44;&#32;&#65;&#91;&#110;&#45;&#49;&#93;&#32;&#43;&#32;&#116;&#95;&#123;&#110;&#45;&#49;&#125;&#32;&#41;&#92;&#93;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\n\n\n\n<p>So, implementing the given specification as a python code, we would get<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def max_subsequence_sum(A):\n\tn = len(A)\n\tif n == 0:\n\t\treturn 0\n\telse:\n\t\treturn max(max_subsequence_sum(A&#91;:n-1]), max_suffix_sum(A&#91;:n]))\n\ndef max_suffix_sum(A):\n\tn = len(A)\n\tif n == 0:\n\t\treturn 0\n\telse:\n\t\treturn max(0, A&#91;n-1] + max_suffix_sum(A&#91;:n-1]))\n<\/code><\/pre>\n\n\n\n<p>Running <em>max_subsequence_sum<\/em> with [5, -3, 4, -7, 8, 7, 4, -1] indeed gives us 19. However, analyzing the code, this top-down approach still runs in <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-45dd599f30859b7d306399fcdc001e32_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;&#94;&#50;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"18\" style=\"vertical-align: 0px;\"\/> time. Even worse, it uses a stack and this stack space grows linearly with n&#8211;size of the input. So, for this approach we have,<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-3e1a7218b2f3a73e9032d26f5810da34_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#84;&#105;&#109;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#32;&#79;&#40;&#110;&#94;&#50;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"20\" width=\"202\" style=\"vertical-align: -5px;\"\/><br><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-23b5cf7a08c3de8851d2591fa87d40ab_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#83;&#112;&#97;&#99;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#32;&#79;&#40;&#110;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"198\" style=\"vertical-align: -5px;\"\/><\/p>\n\n\n\n<p>Although this approach did not give us an advantage over the previous method, we have techniques to improve the stack usage. However, we can implement this in a bottom-up fashion and remove using recursion altogether. Let&#8217;s see how we might do it.<\/p>\n\n\n\n<p><strong>4. Bottom-up approach to calculate maximum subsequence sum<\/strong>. We can optimize the above implementation such that we can compute <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-51fb855de30024c1cbe4003f703f1f0c_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#115;&#95;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"11\" width=\"13\" style=\"vertical-align: -3px;\"\/> immediately after computing <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-3a0a99f018755656447237a37927eecb_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#116;&#95;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"11\" style=\"vertical-align: -3px;\"\/>. Let&#8217;s look at the code how we can implement it. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def max_subsequence_sum(A):\n\tmax_sum = 0\n\tmax_suf_sum = 0\n\tfor i in range(len(A)):\n\t\tmax_suf_sum = max(0, max_suf_sum + A&#91;i])\n\t\tmax_sum = max(max_sum, max_suf_sum)\n\treturn max_sum<\/code><\/pre>\n\n\n\n<p>So, we can see that we have optimized our solution a lot and analyzing this implementation, we find that it runs in linear time <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-a8f81f758e120a3c01f39acbe077ec6d_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> with constant space usage. So, for this implementation, we have<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-ecabf1f9366c6a92208e8e05ebd31e1d_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#84;&#105;&#109;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#79;&#40;&#110;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"194\" style=\"vertical-align: -5px;\"\/><br><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-493f4b9448f74238c1401e3f9b5a46c2_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#83;&#112;&#97;&#99;&#101;&#92;&#32;&#67;&#111;&#109;&#112;&#108;&#101;&#120;&#105;&#116;&#121;&#58;&#32;&#79;&#40;&#49;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"196\" style=\"vertical-align: -5px;\"\/><\/p>\n\n\n\n<p>What if we also want to return the subsequence as well? This should not be too difficult once we understand the above implementation. Let&#8217;s use <em>i_index<\/em> and <em>j_index<\/em> as two variables to keep track of our desired subsequence. Then finally we return subsequence with these two indexes as starting and ending index for the maximum subsequence. Let us see in the code how we can implement it.<\/p>\n\n\n\n<p> <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def max_subsequence_sum(A):\n\tmax_sum = 0\n\tmax_suf_sum = 0\n\ti_index, j_index = 0, 0\n\ttemp_idx = 0\n\n\tfor i in range(len(A)):\n\t\tmax_suf_sum += A&#91;i]\n\t\tif max_suf_sum &gt; max_sum:\n\t\t\tmax_sum = max_suf_sum\n\t\t\tj_index = i\n\t\t\ti_index = temp_idx\n\n\t\tif max_suf_sum &lt; 0:\n\t\t\ttemp_idx = i + 1\n\t\t\tmax_suf_sum = 0\n\n\treturn A&#91;i_index:j_index+1], max_sum<\/code><\/pre>\n\n\n\n<p>This implementation still runs in <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gnikesh.com\/wp-content\/ql-cache\/quicklatex.com-839a1bea811b14b50a5dbd36669826ef_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#79;&#40;&#110;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"38\" style=\"vertical-align: -5px;\"\/> with constant space used. Thank you for making it till the end. Yaay!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>First, let&#8217;s define what a maximum subsequence sum problem is. Suppose we have an array [5, -3, 4, -7, 8, 7, 4, -1] then we would want to find a contiguous sequence that has the maximum sum. In this case, subsequence [8, 7, 4] has the maximum sum i.e. 19. It&#8217;s worth noting that if [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[13,7],"tags":[21,19],"class_list":["post-194","post","type-post","status-publish","format-standard","hentry","category-algorithms-data-structures","category-computer-science","tag-algorithm","tag-computer"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/posts\/194","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/comments?post=194"}],"version-history":[{"count":75,"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/posts\/194\/revisions"}],"predecessor-version":[{"id":280,"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/posts\/194\/revisions\/280"}],"wp:attachment":[{"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/media?parent=194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/categories?post=194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gnikesh.com\/index.php\/wp-json\/wp\/v2\/tags?post=194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}