Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h1>Dynamic Programming: O(N)</h1> <p>It has already mentioned that the problem has a solution by using a <a href="http://en.wikipedia.org/wiki/Pascal%27s_triangle" rel="nofollow">Triangle of Pascal</a>, and its relation to the <a href="http://en.wikipedia.org/wiki/Binomial_coefficient" rel="nofollow">Binomial coefficient</a>. Also the <a href="http://en.wikipedia.org/wiki/Catalan_number" rel="nofollow">Catalan number</a>'s entry has a nice illustration for the <em>n</em> × <em>n</em> case.</p> <h1><em>n</em> × <em>n</em> case</h1> <p>By making use of the aforementioned resources you can conclude that for a grid of size <em>n</em> × <em>n</em> you need to calculate C(2n - 2, n - 1). You can double-check it by rotating the grid by 45 degrees and mapping the Pascal's Triangle.</p> <p>In practical terms, calculating this number directly requires to calculate, in a naive way, at most 3 different factorials which is a very expensive task. If you can pre-calculate them all then there's no discussion here and you can argue this problem has complexity O(1). If you are not interested in the pre-calculated way then you can continue reading.</p> <p>You can calculate such ominous number using Dynamic Programming (DP). The trick here is to perform the operation in smaller steps which won't require you to calculate a large factorial number at all.</p> <p>That is, to calculate C(n, k), you can start by placing yourself at C(n, 1) and walk to C(n, k). Let's start by defining C(n, k) in terms of C(n, k - 1).</p> <pre><code>C(n, k) = n! / k! * ( n - k )! ; k! = (k - 1)! * k = n! / (k - 1)! * k * (n - k)! ; (n - k)! = (n - k + 1)! / (n - k + 1) = n! * (n - k + 1) / (k - 1)! * k * (n - k + 1)! ; C(n, k - 1) = n! / (k - 1)! * ( n - k + 1 )! = C(n, k - 1) * (n - k + 1) / k </code></pre> <p>Based on this, you can define a function to calculate C(n, k) as follows in Python:</p> <pre><code>def C(n, k): """ Calculate C(n, k) using Dynamic Programming. C(n, k) = C(n, k - 1) * (n - k + 1) / k """ C = 1 for ki in range(1, k + 1): C = C * (n - ki + 1) / ki return C </code></pre> <p>It runs in linear time, O(N).</p> <p>For the <em>n</em> × <em>n</em> case you need to calculate C(2n - 2, n - 1).</p> <pre><code>&gt;&gt; print "Response: %dx%d = %d" % (n, n, C(2 * n - 2, n - 1),) Response: 10000x10000 = 5... </code></pre> <h1><em>n</em> × <em>m</em> case</h1> <p>For the general <em>n</em> × <em>m</em> case, you just need to calculate C(n + m - 2, m - 1).</p> <pre><code>&gt;&gt; print "Response: %dx%d = %d" % (n, m, C(n + m - 2, m - 1),) Response: 10000x10000 = 5... </code></pre> <p>Last but not least, <a href="http://ideone.com/BVHNJT" rel="nofollow">you can see a live example at Ideone here.</a></p> <h1>Timings</h1> <p>I ran the algorithm for the following grid sizes.</p> <pre><code> N x N | Response's Length | Time -----------------+-------------------+----------- 1 x 1 | 1 chars | 0.000001 10 x 10 | 5 chars | 0.000004 100 x 100 | 59 chars | 0.000068 1000 x 1000 | 600 chars | 0.002207 10000 x 10000 | 6018 chars | 0.163647 100000 x 100000 | 60203 chars | 40.853971 </code></pre> <p>It seems the operations above a grid size of 100 000 x 100 000 get absurdly expensive due to the very large numbers involved. Nothing to be surprised though.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload