Skip to content

Commit 3ffaab1

Browse files
committed
Added solution to ch4-12 and associated tests.
1 parent 6326715 commit 3ffaab1

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

src/chapter4/ch4-q12.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
/**
4+
* To find all the paths where node values add up to a given sum we need to
5+
* travel all paths of the tree and basically look upwards from the current node
6+
* summing up the values. Where the sum matches the requested sum then increment
7+
* counter. Even if we match the requested sum or go over we still need to keep
8+
* going up the path as negative values are also allowed.
9+
*
10+
* N = |tree|
11+
* Time: O(N lg N) - assuming a balanced tree, worst case O(N^2)
12+
* Additional space: O(lg N) - assuming a balanced tree, worst case O(N)
13+
*/
14+
export function findPathWithSum(tree, value) {
15+
if (!tree || !tree.root) {
16+
throw new Error('tree must be valid and non-empty');
17+
}
18+
19+
return findPathWithSumRecurse([], tree.root, value);
20+
}
21+
22+
function findPathWithSumRecurse(path, node, value) {
23+
let count = 0;
24+
if (node) {
25+
path.push(node.val);
26+
let sum = 0;
27+
for (let i = path.length - 1; i >= 0; --i) {
28+
sum += path[i];
29+
if (sum === value) {
30+
++count;
31+
}
32+
}
33+
count += findPathWithSumRecurse(path, node.left, value) +
34+
findPathWithSumRecurse(path, node.right, value);
35+
path.pop();
36+
}
37+
return count;
38+
}

src/chapter4/ch4-q12.spec.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { expect } from 'chai';
2+
import { Tree } from './helpers';
3+
import * as funcs from './ch4-q12';
4+
5+
for (let key in funcs) {
6+
let func = funcs[key];
7+
8+
describe('ch4-q12: ' + key, function() {
9+
10+
beforeEach(function() {
11+
this.tree = new Tree();
12+
});
13+
14+
it('throws an error if tree is null or empty', function() {
15+
expect(() => func(null, 10)).to.throw('tree must be valid and non-empty');
16+
expect(() => func(this.tree)).to.throw('tree must be valid and non-empty');
17+
});
18+
19+
it('returns 0 when no paths sum to value', function() {
20+
[10, 9, 11, 8, 7, 6].forEach(v => this.tree.add(v));
21+
expect(func(this.tree, 50)).to.eql(0);
22+
expect(func(this.tree, 5)).to.eql(0);
23+
});
24+
25+
it('returns correct counts with balanced tree', function() {
26+
[8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15].forEach(v => this.tree.add(v));
27+
expect(func(this.tree, 1)).to.equal(1);
28+
expect(func(this.tree, 5)).to.equal(2);
29+
expect(func(this.tree, 10)).to.equal(2);
30+
expect(func(this.tree, 11)).to.equal(2);
31+
});
32+
33+
it('returns correct counts with unbalanced tree', function() {
34+
[10, 8, 16, 4, 14, 22, 6, 12, 18, 5, 17, 19].forEach(v => this.tree.add(v));
35+
expect(func(this.tree, 10)).to.equal(2);
36+
expect(func(this.tree, 18)).to.equal(3);
37+
});
38+
39+
it('returns correct counts with lots of paths that equal value', function() {
40+
[50, 10, 80, 40, 70, 150, 20, 30].forEach(v => this.tree.add(v));
41+
expect(func(this.tree, 50)).to.equal(3);
42+
expect(func(this.tree, 150)).to.equal(3);
43+
});
44+
45+
});
46+
47+
}

0 commit comments

Comments
 (0)