You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Combinatorics/README.markdown
+39-41Lines changed: 39 additions & 41 deletions
Original file line number
Diff line number
Diff line change
@@ -304,7 +304,43 @@ combinations(28, 5) // prints 98280
304
304
305
305
Because this uses the `permutations()` and `factorial()` functions under the hood, you're still limited by how large these numbers can get. For example, `combinations(30, 15)` is "only" `155,117,520` but because the intermediate results don't fit into a 64-bit integer, you can't calculate it with the given function.
306
306
307
-
Here is an algorithm that uses dynamic programming to overcome the need for calculating factorials. It is based on Pascal's triangle:
307
+
There's a faster approach to calculate `C(n, k)` in **O(k)** time and **O(1)** extra space. The idea behind it is that the formula for `C(n, k)` is:
This algorithm can create larger numbers than the previous method. Instead of calculating the entire numerator (a potentially huge number) and then dividing it by the factorial (also a very large number), here we already divide in each step. That causes the temporary results to grow much less quickly.
333
+
334
+
Here's how you can use this improved algorithm:
335
+
336
+
```swift
337
+
quickBinomialCoefficient(8, 2) // prints 28
338
+
quickBinomialCoefficient(30, 15) // prints 155117520
339
+
```
340
+
341
+
This new method is quite fast but you're still limited in how large the numbers can get. You can calculate `C(30, 15)` without any problems, but something like `C(66, 33)` will still cause integer overflow in the numerator.
342
+
343
+
Here is an algorithm that uses dynamic programming to overcome the need for calculating factorials and doing divisions. It is based on Pascal's triangle:
This uses [Array2D](../Array2D/) as helper code because Swift doesn't have a built-in two-dimensional array. The algorithm itself is quite simple: the first loop fills in the 1s at the outer edges of the triangle. The other loops calculate each number in the triangle by adding up the two numbers from the previous row.
353
389
354
-
Now you can calculate `C(30, 15)` without any problems:
390
+
Now you can calculate `C(66, 33)` without any problems:
355
391
356
392
```swift
357
-
binomialCoefficient(30, 15) // prints 155117520
358
393
binomialCoefficient(66, 33) // prints a very large number
359
394
```
360
395
361
-
There's a faster approach to calculate `C(n, k)` in `O(k)` time and `O(1)` extra space.
362
-
363
-
The idea behind it is that the formula for `C(n, k)` is:
As there're the divisors for numbers from `1...k` among `k` consecutive numbers, what is exactly we've got in the numerator of our fast formula every time we devide `result` by `(i + 1)` we won't have a real number.
390
-
391
-
Here's how you can use it:
392
-
393
-
```swift
394
-
quickBinomialCoefficient(30, 15) // prints 155117520
395
-
quickBinomialCoefficient(8, 2) // prints 28
396
-
```
397
-
398
396
You may wonder what the point is in calculating these permutations and combinations, but many algorithm problems are really combinatorics problems in disguise. Often you may need to look at all possible combinations of your data to see which one gives the right solution. If that means you need to search through `n!` potential solutions, you may want to consider a different approach -- as you've seen, these numbers become huge very quickly!
399
397
400
398
## References
401
399
402
400
Wirth's and Sedgewick's permutation algorithms and the code for counting permutations and combinations are based on the Algorithm Alley column from Dr.Dobb's Magazine, June 1993. The dynamic programming binomial coefficient algorithm is from The Algorithm Design Manual by Skiena.
403
401
404
-
*Written for Swift Algorithm Club by Matthijs Hollemans*
402
+
*Written for Swift Algorithm Club by Matthijs Hollemans and [Kanstantsin Linou](https://github.com/nuts23)*
0 commit comments