forked from trekhleb/javascript-algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
79 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,68 @@ | ||
# Fast Powering Algorithm | ||
|
||
This computes power of (a,b) | ||
eg: power(2,3) = 8 | ||
power(10,0) = 1 | ||
**The power of a number** says how many times to use the number in a | ||
multiplication. | ||
|
||
The algorithm uses divide and conquer approach to compute power. | ||
Currently the algorithm work for two positive integers X and Y | ||
Lets say there are two numbers X and Y. | ||
At each step of the algorithm: | ||
1. if Y is even | ||
then power(X, Y/2) * power(X, Y/2) is computed | ||
2. if Y is odd | ||
then X * power(X, Y/2) * power(X, Y/2) is computed | ||
It is written as a small number to the right and above the base number. | ||
|
||
At each step since power(X,Y/2) is called twice, this is optimised by saving the result of power(X, Y/2) in a variable (lets say res). | ||
And then res is multiplied by self. | ||
![Power](https://www.mathsisfun.com/algebra/images/exponent-8-2.svg) | ||
|
||
Illustration through example | ||
power (2,5) | ||
- 2 * power(2,2) * power(2,2) | ||
power(2,2) | ||
- power(2,1) * power(2,1) | ||
power(2,1) | ||
- return 2 | ||
## Naive Algorithm Complexity | ||
|
||
Going up the tree once the end values are computed | ||
power(2,1) = 2 | ||
power(2,2) = power(2,1) * power(2,1) = 2 * 2 = 4 | ||
power(2,5) = 2 * power(2,2) * power(2,2) = 2 * 4 * 4 = 32 | ||
How to find `a` raised to the power `b`? | ||
|
||
We multiply `a` to itself, `b` times. That | ||
is, `a^b = a * a * a * ... * a` (`b` occurrences of `a`). | ||
|
||
Complexity relation: T(n) = T(n/2) + 1 | ||
This operation will take `O(n)` time since we need to do multiplication operation | ||
exactly `n` times. | ||
|
||
Time complexity of the algorithm: O(logn) | ||
## Fast Power Algorithm | ||
|
||
## References | ||
Can we do better than naive algorithm does? Yes we may solve the task of | ||
powering in `O(log(n))` time. | ||
|
||
The algorithm uses divide and conquer approach to compute power. Currently the | ||
algorithm work for two positive integers `X` and `Y`. | ||
|
||
The idea behind the algorithm is based on the fact that: | ||
|
||
For **even** `Y`: | ||
|
||
```text | ||
X^Y = X^(Y/2) * X^(Y/2) | ||
``` | ||
|
||
For **odd** `Y`: | ||
|
||
```text | ||
X^Y = X^(Y//2) * X^(Y//2) * X | ||
where Y//2 is result of division of Y by 2 without reminder. | ||
``` | ||
|
||
**For example** | ||
|
||
```text | ||
2^4 = (2 * 2) * (2 * 2) = (2^2) * (2^2) | ||
``` | ||
|
||
```text | ||
2^5 = (2 * 2) * (2 * 2) * 2 = (2^2) * (2^2) * (2) | ||
``` | ||
|
||
Now, since on each step we need to compute the same `X^(Y/2)` power twice we may optimise | ||
it by saving it to some intermediate variable to avoid its duplicate calculation. | ||
|
||
**Time Complexity** | ||
|
||
Since each iteration we split the power by half then we will call function | ||
recursively `log(n)` times. This the time complexity of the algorithm is reduced to: | ||
|
||
```text | ||
O(log(n)) | ||
``` | ||
|
||
## References | ||
|
||
- [YouTube](https://www.youtube.com/watch?v=LUWavfN9zEo&index=80&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&t=0s) | ||
- [Wikipedia](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,30 @@ | ||
/** | ||
* Fast Powering Algorithm. | ||
* Recursive implementation to compute power. | ||
* | ||
* @param {number} number1 | ||
* @param {number} number2 | ||
* Complexity: log(n) | ||
* | ||
* @param {number} base - Number that will be raised to the power. | ||
* @param {number} power - The power that number will be raised to. | ||
* @return {number} | ||
*/ | ||
export default function fastPowering(number1, number2) { | ||
let val = 0; | ||
let res = 0; | ||
if (number2 === 0) { // if number2 is 0 | ||
val = 1; | ||
} else if (number2 === 1) { // if number2 is 1 return number 1 as it is | ||
val = number1; | ||
} else if (number2 % 2 === 0) { // if number2 is even | ||
res = fastPowering(number1, number2 / 2); | ||
val = res * res; | ||
} else { // if number2 is odd | ||
res = fastPowering(number1, Math.floor(number2 / 2)); | ||
val = res * res * number1; | ||
export default function fastPowering(base, power) { | ||
if (power === 0) { | ||
// Anything that is raised to the power of zero is 1. | ||
return 1; | ||
} | ||
|
||
if (power % 2 === 0) { | ||
// If the power is even... | ||
// we may recursively redefine the result via twice smaller powers: | ||
// x^8 = x^4 * x^4. | ||
const multiplier = fastPowering(base, power / 2); | ||
return multiplier * multiplier; | ||
} | ||
return val; | ||
|
||
// If the power is odd... | ||
// we may recursively redefine the result via twice smaller powers: | ||
// x^9 = x^4 * x^4 * x. | ||
const multiplier = fastPowering(base, Math.floor(power / 2)); | ||
return multiplier * multiplier * base; | ||
} |