Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: trekhleb/javascript-algorithms
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8a53ea1
Choose a base ref
...
head repository: trekhleb/javascript-algorithms
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c4eead4
Choose a head ref
  • 8 commits
  • 7 files changed
  • 5 contributors

Commits on Oct 17, 2018

  1. Add prepend and fix bug (#227)

    Add prepend operation and fix some mistake in pseudocode.
    kiinlam authored and trekhleb committed Oct 17, 2018
    Copy the full SHA
    044441e View commit details
  2. BubbleSort: use Destructuring assignment to swap values (#226)

    * BubbleSort: use Destructuring assignment to swap values
    
    * lint: add semi
    SidKwok authored and trekhleb committed Oct 17, 2018
    Copy the full SHA
    5d12638 View commit details
  3. Properly detect min and max element in array (#224)

    Yavorski authored and trekhleb committed Oct 17, 2018
    Copy the full SHA
    6bd6072 View commit details

Commits on Oct 18, 2018

  1. fix typo error (#228)

    catchme authored and trekhleb committed Oct 18, 2018
    Copy the full SHA
    fad170c View commit details
  2. Copy the full SHA
    42b5a46 View commit details
  3. add partial README

    appleJax committed Oct 18, 2018
    Copy the full SHA
    4b67f1e View commit details
  4. finish README

    appleJax committed Oct 18, 2018
    Copy the full SHA
    0cdb6b3 View commit details
  5. fix typos

    appleJax committed Oct 18, 2018
    Copy the full SHA
    c4eead4 View commit details
41 changes: 41 additions & 0 deletions src/algorithms/math/karatsuba-multiplication/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Karatsuba Multiplication

Karatsuba is a fast multiplication algorithm discovered by Anatoly Karatsuba in 1960. Given two n-digit numbers, the "grade-school" method of long multiplication has a time complexity of O(n<sup>2</sup>), whereas the karatsuba algorithm has a time complexity of O(n<sup>1.59</sup>).

## Recursive Formula

```
x = 1234
y = 5678
karatsuba(x, y)
```

1. Split each number into numbers with half as many digits
```
a = 12
b = 34
c = 56
d = 78
```

2. Compute 3 subexpressions from the smaller numbers
- `ac = a * c`
- `bd = b * d`
- `abcd = (a + b) * (c + d)`

3. Combine subexpressions to calculate the product
```
A = ac * 10000
B = (abcd - ac - bd) * 100
C = bd
x * y = A + B + C
```

_**Note:**_ *The karatsuba algorithm can be applied recursively to calculate each product in the subexpressions.* (`a * c = karatsuba(a, c)`*). When the numbers get smaller than some arbitrary threshold, they are multiplied in the traditional way.*

## References
[Stanford Algorithms (YouTube)](https://www.youtube.com/watch?v=JCbZayFr9RE)
[Wikipedia](https://en.wikipedia.org/wiki/Karatsuba_algorithm)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import karatsuba from '../karatsuba';

describe('karatsuba multiplication', () => {
it('should multiply simple numbers correctly', () => {
expect(karatsuba(0, 37)).toEqual(0);
expect(karatsuba(1, 8)).toEqual(8);
expect(karatsuba(5, 6)).toEqual(30);
});

it('should multiply larger numbers correctly', () => {
expect(karatsuba(1234, 5678)).toEqual(7006652);
expect(karatsuba(9182734, 726354172)).toEqual(6669917151266248);
});
});
68 changes: 68 additions & 0 deletions src/algorithms/math/karatsuba-multiplication/karatsuba.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
*
* @param {number} x
* @param {number} y
* @return {number}
*/
export default function karatsuba(x, y) {
// BASE CASE:
// if numbers are sufficiently small,
// multiply them together in the traditional way
if (x < 10 || y < 10) {
return x * y;
}

// SCALE FACTOR:
// scaleFactor is used to split the numbers
// into smaller numbers for recursion.
// when combining the subexpressions back
// together, the scaleFactor is used to
// recreate the magnitude of the original numbers
const minDigits = Math.min(
String(x).length,
String(y).length,
);
const scaleFactor = 10 ** Math.floor(minDigits / 2);

// PARAMETER COMPONENTS:
// a b are the two components of x
// c d are the two components of y
//
// e.g.
// x = 1234 -> a = 12, b = 34
// y = 5678 -> c = 56, d = 78

// example of component computations:
// x = 1234, y = 5678
// scaleFactor = 100

// a = floor(1234 / 100) = floor(12.34) = 12
const a = Math.floor(x / scaleFactor);

// b = 1234 - (12 * 100) = 1234 - 1200 = 34
const b = x - (a * scaleFactor);

// c = floor(5678 / 100) = floor(56.78) = 56
const c = Math.floor(y / scaleFactor);

// d = 5678 - (56 * 100) = 5678 - 5600 = 78
const d = y - (c * scaleFactor);

// COMPUTE SUBEXPRESSIONS:
// since a + b is less than x, and c + d is less than y
// the recursion is guaranteed to reach the base case
const ac = karatsuba(a, c);
const bd = karatsuba(b, d);
const abcd = karatsuba(a + b, c + d);

// COMBINE SUBEXPRESSIONS:
// since the scaleFactor was used to
// reduce the size of the components,
// the scaleFactor must be applied in reverse
// to reconstruct the magnitude of the original components
const A = ac * (scaleFactor ** 2);
const B = (abcd - ac - bd) * scaleFactor;
const C = bd;

return A + B + C;
}
4 changes: 1 addition & 3 deletions src/algorithms/sorting/bubble-sort/BubbleSort.js
Original file line number Diff line number Diff line change
@@ -19,9 +19,7 @@ export default class BubbleSort extends Sort {

// Swap elements if they are in wrong order.
if (this.comparator.lessThan(array[j + 1], array[j])) {
const tmp = array[j + 1];
array[j + 1] = array[j];
array[j] = tmp;
[array[j], array[j + 1]] = [array[j + 1], array[j]];

// Register the swap.
swapped = true;
Original file line number Diff line number Diff line change
@@ -27,14 +27,10 @@ describe('CountingSort', () => {
const sorter = new CountingSort({ visitingCallback });

// Detect biggest number in array in prior.
const biggestElement = notSortedArr.reduce((accumulator, element) => {
return element > accumulator ? element : accumulator;
}, 0);
const biggestElement = Math.max(...notSortedArr);

// Detect smallest number in array in prior.
const smallestElement = notSortedArr.reduce((accumulator, element) => {
return element < accumulator ? element : accumulator;
}, 0);
const smallestElement = Math.min(...notSortedArr);

const sortedArray = sorter.sort(notSortedArr, smallestElement, biggestElement);

27 changes: 20 additions & 7 deletions src/data-structures/linked-list/README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -28,7 +28,20 @@ Add(value)
end if
end Add
```


```
Prepend(value)
Pre: value is the value to add to the list
Post: value has been placed at the head of the list
n ← node(value)
n.next ← head
head ← n
if tail = ø
tail ← n
end
end Prepend
```

### 搜索

```text
@@ -67,10 +80,10 @@ Remove(head, value)
end if
return true
end if
while n.next = ø and n.next.value = value
while n.next != ø and n.next.value != value
n ← n.next
end while
if n.next = ø
if n.next != ø
if n.next = tail
tail ← n
end if
@@ -88,7 +101,7 @@ Traverse(head)
Pre: head is the head node in the list
Post: the items in the list have been traversed
n ← head
while n = 0
while n != 0
yield n.value
n ← n.next
end while
@@ -101,11 +114,11 @@ end Traverse
ReverseTraversal(head, tail)
Pre: head and tail belong to the same list
Post: the items in the list have been traversed in reverse order
if tail = ø
if tail != ø
curr ← tail
while curr = head
while curr != head
prev ← head
while prev.next = curr
while prev.next != curr
prev ← prev.next
end while
yield curr.value
2 changes: 1 addition & 1 deletion src/data-structures/tree/fenwick-tree/FenwickTree.js
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ export default class FenwickTree {
*/
queryRange(leftIndex, rightIndex) {
if (leftIndex > rightIndex) {
throw new Error('Left index can not be greater then right one');
throw new Error('Left index can not be greater than right one');
}

if (leftIndex === 1) {