Skip to content

[pull] master from amejiarosario:master #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(book/bt): add binary tree diameter problem
  • Loading branch information
amejiarosario committed Sep 1, 2020
commit 068dd9cc66e5a3050cc44d4cd3a05eb15f8c00d1
78 changes: 78 additions & 0 deletions book/D-interview-questions-solutions.asc
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,84 @@ As you can see, we opted for using a set to trade speed for memory.



:leveloffset: +1

=== Solutions for Binary Tree Questions
(((Interview Questions Solutions, Binary Tree)))

:leveloffset: -1

[#binary-tree-q-diameter-of-binary-tree]
include::content/part03/tree-intro.asc[tag=binary-tree-q-diameter-of-binary-tree]

We are asked to find the longest path on binary tree that might or might not pass through the root node.

We can calculate the height (distance from root to farthest leaf) of a binary tree using this recursive function:

[source, javascript]
----
function getHeight(node) {
if (!node) return 0;
const leftHeight = getHeight(node.left);
const rightHeight = getHeight(node.right);
return 1 + Math.max(leftHeight, rightHeight);
}
----

That will give use the height from furthest leaf to root. However, the problem says that it might or might not go through the root.
In that case, we can keep track of the maximun distance (`leftHeight + rightHeight`) seen so far.

*Algorithm*:

- Initialize diameter to `0`
- Recursively find the height of the tree from root.
- Keep track of the maximun diameter length seen so far (left + right).
- Return the diameter.

*Implementation*:

[source, javascript]
----
include::interview-questions/diameter-of-binary-tree.js[tags=description;solution]
----

We are using `Math.max` to keep track of the longest diameter seen.

*Complexity Analysis*:

- Time: `O(n)`, where `n` is each one of the nodes on the tree. We visite each one once.
- Space: `O(n)`. We use `O(1)` variables, but because we are using the `height` recursive function we are using the implicit call stack, thus `O(n)`.




[#binary-tree-q-diameter-of-binary-tree2]
include::content/part03/tree-intro.asc[tag=binary-tree-q-diameter-of-binary-tree]

RESTATE REQUIREMENTS AND DESCRIPTIONS

*Algorithm*:

- STEP 1
- STEP 2
- STEP 2.1
- STEP 2.2

*Implementation*:

[source, javascript]
----
include::interview-questions/diameter-of-binary-tree.js[tag=description]
include::interview-questions/diameter-of-binary-tree.js[tag=solution]
----

IMPLEMENTATION NOTES

*Complexity Analysis*:

- Time: `O(?)`. WHY?
- Space: `O(?)`. WHY?


// [#linkedlist-q-FILENAME]
// include::content/part02/linked-list.asc[tag=linkedlist-q-FILENAME]
Expand Down
2 changes: 1 addition & 1 deletion book/config
103 changes: 103 additions & 0 deletions book/content/part03/tree-intro.asc
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,106 @@ image::image35.png[image,width=258,height=169]
Heap is better at finding max or min values in constant time *O(1)*, while a balanced BST is good a finding any element in *O(log n)*. Heaps are often used to implement priority queues while BST is used when you need every value sorted.
****
indexterm:[Runtime, Logarithmic]


==== Practice Questions
(((Interview Questions, Binary Tree)))


// tag::binary-tree-q-diameter-of-binary-tree[]
===== Binary Tree Diameter

*BT-1*) _Find the diameter of a binary tree. The diameter of a tree is defined as the longest possible path from two nodes (it doesn't need to include the root). The lenth of diameter is calculated by couting the number of edges on the path._

// end::binary-tree-q-diameter-of-binary-tree[]

_Seen in interviews at: Facebook, Amazon, Google_

Example 1:

[graphviz, tree-diameter-example-1, png]
....
graph G {
1 -- 2 [color=red]
1 -- 3 [color=red]

2 -- 4
2 -- 5 [color=red]
}
....

[source, javascript]
----
diameterOfBinaryTree(toBinaryTree([1,2,3,4,5])); // 3 (the path 3-1-2-5 or 3-1-2-4)
----

Example 2:

[graphviz, tree-diameter-example-2, png]
....
graph G {
1
2
3
4
5
6
"null" [color=white, fontcolor = white]
"null." [color=white, fontcolor = white]
7
8
"null.." [color=white, fontcolor = white]
"null..." [color=white, fontcolor = white]
9

1 -- 2
1 -- 3

3 -- 4 [color=red]
3 -- 5 [color=red]

4 -- 6 [color=red]
4 -- "null." [color=white]

5 -- "null" [color=white]
5 -- 7 [color=red]

6 -- 8 [color=red]
6 -- "null.." [color=white]

7 -- "null..." [color=white]
7 -- 9 [color=red]
}
....

[source, javascript]
----
diameterOfBinaryTree(toBinaryTree([1,2,3,null,null,4,5,6,null,null,7,8,null,null,9])); // 6 (the path 8-6-4-3-5-7-9)
----

Starter code:

[source, javascript]
----
include::../../interview-questions/diameter-of-binary-tree.js[tags=description;placeholder]
----


_Solution: <>_



// tag::binary-tree-q-FILENAME[]
===== Recent Counter

*BT-2*) _._

Example:

[source, javascript]
----

----

_Seen in interviews at: X_
// end::binary-tree-q-FILENAME[]
Binary file added book/images/tree-diameter-example-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added book/images/tree-diameter-example-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions book/interview-questions/diameter-of-binary-tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// tag::description[]
/**
* Find the length of the binary tree diameter.
*
* @param {BinaryTreeNode | null} root - Binary Tree's root.
* @returns {number} tree's diameter (longest possible path on the tree)
*/
function diameterOfBinaryTree(root) {
// end::description[]
// tag::placeholder[]
// write your code here...
// end::placeholder[]
// tag::solution[]
let diameter = 0;

const height = (node) => {
if (!node) return 0;
const left = height(node.left);
const right = height(node.right);
diameter = Math.max(diameter, left + right);
return 1 + Math.max(left, right);
};

height(root);
return diameter;
// end::solution[]
// tag::description[]
}
// end::description[]

module.exports = { diameterOfBinaryTree };
21 changes: 21 additions & 0 deletions book/interview-questions/diameter-of-binary-tree.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { diameterOfBinaryTree } = require('./diameter-of-binary-tree');
const { BinaryTreeNode } = require('../../src/index');

describe('Binary Tree: Diameter', () => {
function toBinaryTree(array, index = 0) {
if (index >= array.length) return null;
const node = new BinaryTreeNode(array[index]);
node.left = toBinaryTree(array, index * 2 + 1);
node.right = toBinaryTree(array, index * 2 + 2);
return node;
}

it('should find the diameter', () => {
expect(diameterOfBinaryTree(toBinaryTree([1, 2, 3, 4, 5]))).toEqual(3);
});

it('should find the diameter when does not pass through the root node', () => {
const tree = [1, 2, 3, null, null, 4, 5, 6, null, null, 7, 8, null, null, 9];
expect(diameterOfBinaryTree(toBinaryTree(tree))).toEqual(6);
});
});