{"id":611,"date":"2008-12-07T13:17:07","date_gmt":"2008-12-07T12:17:07","guid":{"rendered":"http:\/\/www.navision-blog.de\/2008\/12\/07\/subsetsum-in-ons\/"},"modified":"2022-12-30T13:29:50","modified_gmt":"2022-12-30T13:29:50","slug":"subsetsum-in-ons","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2008\/12\/07\/subsetsum-in-ons\/","title":{"rendered":"SubsetSum in O(nS)"},"content":{"rendered":"<p>The &#8220;Subset Sum&#8221;-problem is given as the following:<\/p>\n<blockquote>\n<p>SUBSET SUM<br \/>Input: Numbers a<sub>1<\/sub>, a<sub>2<\/sub>, . . . , a<sub>n<\/sub>, S \u2208 N. <br \/>Question: Is there a subset I \u2286 {1,&#8230;,n} with \u2211 a<sub>i<\/sub> = S? <\/p>\n<\/blockquote>\n<p>Finding a solution for this decision problem is a very easy task in F#.<\/p>\n<pre class=\"code\"><span style=\"color: blue\">let <\/span>hasSubsetSum_Naive (numbers: int list) S =\n  <span style=\"color: blue\">let rec <\/span>hasSubsetSum (a: int list) lastSum =\n    <span style=\"color: blue\">match <\/span>a <span style=\"color: blue\">with \n      <\/span>| [] <span style=\"color: blue\">-&gt; false\n      <\/span>| x::rest <span style=\"color: blue\">-&gt; \n        if <\/span>lastSum + x = S <span style=\"color: blue\">then\n          true\n        elif <\/span>lastSum + x &gt; S <span style=\"color: blue\">then\n          false\n        else\n          <\/span>hasSubsetSum rest lastSum || hasSubsetSum rest (lastSum+x)\n  \n  hasSubsetSum numbers 0\n\n<span style=\"color: blue\">let <\/span>numbers = [ 5;4;3;6;7;12 ]\n<span style=\"color: blue\">let <\/span>searchedSum = 33  \nhasSubsetSum_Naive numbers searchedSum<\/pre>\n<p>Of course this small program can be easily adjusted to give the subset I back. Unfortunately this na\u00efve approach leads to a running time of O(2^n). <\/p>\n<p>But if S is small we can build a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Dynamic_programming\">dynamic program<\/a> and decide the problem in O(n*S) time. <\/p>\n<p>&nbsp;<img loading=\"lazy\" style=\"border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"50\" alt=\"\" src=\"http:\/\/www.navision-blog.de\/images\/SubsetSuminOnS_BAAE\/Uebung4_Forkmann14x.png\" width=\"317\" border=\"0\"> <\/p>\n<p><img loading=\"lazy\" style=\"border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"50\" alt=\"\" src=\"http:\/\/www.navision-blog.de\/images\/SubsetSuminOnS_BAAE\/Uebung4_Forkmann15x.png\" width=\"336\" border=\"0\"> <\/p>\n<p><img loading=\"lazy\" style=\"border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"50\" alt=\"\" src=\"http:\/\/www.navision-blog.de\/images\/SubsetSuminOnS_BAAE\/Uebung4_Forkmann16x.png\" width=\"270\" border=\"0\"> <\/p>\n<p>This can be easily transformed into F# code. <\/p>\n<pre class=\"code\"><span style=\"color: blue\">let <\/span>hasSubsetSum (numbers: int array) S =\n   <span style=\"color: blue\">if <\/span>numbers |&gt; Array.exists (<span style=\"color: blue\">fun <\/span>x <span style=\"color: blue\">-&gt; <\/span>x = S) <span style=\"color: blue\">then\n     true\n   else\n     let <\/span>a = numbers |&gt; Array.filter (<span style=\"color: blue\">fun <\/span>x <span style=\"color: blue\">-&gt; <\/span>x &lt; S)      \n     <span style=\"color: blue\">let <\/span>n = a.Length\n     <span style=\"color: blue\">if <\/span>n = 0 <span style=\"color: blue\">then\n       false\n     else\n       let <\/span>v = Array2.create n (S+1) 0\n       <span style=\"color: blue\">let <\/span>u = Array2.create n (S+1) <span style=\"color: blue\">false\n       let <\/span>t = Array2.create n (S+1) 0\n       \n       <span style=\"color: blue\">for <\/span>j <span style=\"color: blue\">in <\/span>[1..S] <span style=\"color: blue\">do\n         for <\/span>i <span style=\"color: blue\">in <\/span>[0..n-1] <span style=\"color: blue\">do                           \n           if <\/span>j - a.[i] &gt;= 0 &amp;&amp; not u.[i,j - a.[i]] <span style=\"color: blue\">then\n             <\/span>v.[i,j] &lt;- t.[i,j - a.[i]] + a.[i]\n           <span style=\"color: blue\">if <\/span>((i = 0) || (i &gt; 0 &amp;&amp; t.[i-1,j] &lt;&gt; j)) &amp;&amp; v.[i,j] = j <span style=\"color: blue\">then\n             <\/span>u.[i,j] &lt;- <span style=\"color: blue\">true\n           if <\/span>v.[i,j] = j <span style=\"color: blue\">then\n             <\/span>t.[i,j] &lt;- j\n           <span style=\"color: blue\">else\n             if <\/span>i &gt; 0 <span style=\"color: blue\">then\n               <\/span>t.[i,j] &lt;- max t.[i-1,j] t.[i,j-1]\n             <span style=\"color: blue\">else\n               <\/span>t.[i,j] &lt;- t.[0,j-1]\n               \n       <strong>t.[n-1,S] = S<\/strong><\/pre>\n<div style=\"font-size:0px;\"><a href=\"https:\/\/kopapilleronline.com\">https:\/\/kopapilleronline.com<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The &#8220;Subset Sum&#8221;-problem is given as the following: SUBSET SUMInput: Numbers a1, a2, . . . , an, S \u2208 N. Question: Is there a subset I \u2286 {1,&#8230;,n} with \u2211 ai = S? Finding a solution for this decision problem is a very easy task in F#. let hasSubsetSum_Naive (numbers: int list) S = [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[23,448,8],"tags":[484,469,664,483],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/611"}],"collection":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=611"}],"version-history":[{"count":3,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/611\/revisions"}],"predecessor-version":[{"id":2041,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/611\/revisions\/2041"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=611"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=611"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}