Reorganized instruction text on multiple challenges (#35912)
* Reorganized instruction text on multiple challenges * Fixed spaces * Fixed spaces again * Update curriculum/challenges/english/08-coding-interview-prep/data-structures/add-elements-at-a-specific-index-in-a-linked-list.english.md Co-Authored-By: Randell Dawson <5313213+RandellDawson@users.noreply.github.com> * Update curriculum/challenges/english/08-coding-interview-prep/data-structures/find-the-minimum-and-maximum-height-of-a-binary-search-tree.english.md Co-Authored-By: Randell Dawson <5313213+RandellDawson@users.noreply.github.com> * fix: added code tags
This commit is contained in:
@ -29,126 +29,120 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.add !== 'function') { return false; }; test.add(4); test.add(1); test.add(7); test.add(87); test.add(34); test.add(45); test.add(73); test.add(8); const expectedResult = [ 1, 4, 7, 8, 34, 45, 73, 87 ]; const result = test.inOrder(); return (expectedResult.toString() === result.toString()); })(), 'The add method adds elements according to the binary search tree rules.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.add !== 'function') { return false; }; test.add(4); test.add(1); test.add(7); test.add(87); test.add(34); test.add(45); test.add(73); test.add(8); const expectedResult = [ 1, 4, 7, 8, 34, 45, 73, 87 ]; const result = test.inOrder(); return (expectedResult.toString() === result.toString()); })(), 'The add method adds elements according to the binary search tree rules.');
|
||||||
- text: Adding an element that already exists returns <code>null</code>
|
- text: Adding an element that already exists returns <code>null</code>
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.add !== 'function') { return false; }; test.add(4); return test.add(4) == null; })(), 'Adding an element that already exists returns <code>null</code>');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.add !== 'function') { return false; }; test.add(4); return test.add(4) == null; })(), 'Adding an element that already exists returns <code>null</code>');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// change code below this line
|
// change code below this line
|
||||||
// change code above this line
|
// change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
isBinarySearchTree() {
|
isBinarySearchTree() {
|
||||||
if (this.root == null) {
|
if (this.root == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
var check = true;
|
var check = true;
|
||||||
function checkTree(node) {
|
function checkTree(node) {
|
||||||
if (node.left != null) {
|
if (node.left != null) {
|
||||||
var left = node.left;
|
var left = node.left;
|
||||||
if (left.value > node.value) {
|
if (left.value > node.value) {
|
||||||
check = false;
|
check = false;
|
||||||
} else {
|
} else {
|
||||||
checkTree(left);
|
checkTree(left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node.right != null) {
|
if (node.right != null) {
|
||||||
var right = node.right;
|
var right = node.right;
|
||||||
if (right.value < node.value) {
|
if (right.value < node.value) {
|
||||||
check = false;
|
check = false;
|
||||||
} else {
|
} else {
|
||||||
checkTree(right);
|
checkTree(right);
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
checkTree(this.root);
|
checkTree(this.root);
|
||||||
return check;
|
return check;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
inOrder() {
|
inOrder() {
|
||||||
if (!this.root) { return null; }
|
if (!this.root) {
|
||||||
var result = new Array();
|
return null;
|
||||||
function traverseInOrder(node) {
|
|
||||||
node.left && traverseInOrder(node.left);
|
|
||||||
result.push(node.value);
|
|
||||||
node.right && traverseInOrder(node.right);
|
|
||||||
}
|
|
||||||
traverseInOrder(this.root);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
var result = new Array();
|
||||||
|
function traverseInOrder(node) {
|
||||||
|
node.left && traverseInOrder(node.left);
|
||||||
|
result.push(node.value);
|
||||||
|
node.right && traverseInOrder(node.right);
|
||||||
|
}
|
||||||
|
traverseInOrder(this.root);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
this.add = function (element) {
|
this.add = function(element) {
|
||||||
let current = this.root;
|
let current = this.root;
|
||||||
if (!current) {
|
if (!current) {
|
||||||
this.root = new Node(element)
|
this.root = new Node(element);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const searchTree = function (current) {
|
const searchTree = function(current) {
|
||||||
if (current.value > element) {
|
if (current.value > element) {
|
||||||
if (current.left) { //si existe
|
if (current.left) {
|
||||||
return searchTree(current.left)
|
//si existe
|
||||||
} else {
|
return searchTree(current.left);
|
||||||
current.left = new Node(element);
|
} else {
|
||||||
return;
|
current.left = new Node(element);
|
||||||
}
|
return;
|
||||||
} else if (current.value < element) {
|
}
|
||||||
if (current.right) {
|
} else if (current.value < element) {
|
||||||
return searchTree(current.right)
|
if (current.right) {
|
||||||
} else {
|
return searchTree(current.right);
|
||||||
current.right = new Node(element)
|
} else {
|
||||||
return;
|
current.right = new Node(element);
|
||||||
}
|
return;
|
||||||
} else {
|
}
|
||||||
return null;
|
} else {
|
||||||
}
|
return null;
|
||||||
}
|
}
|
||||||
return searchTree(current);
|
};
|
||||||
}
|
return searchTree(current);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -9,15 +9,12 @@ challengeType: 1
|
|||||||
Let's create a addAt(index,element) method that adds an element at a given index.
|
Let's create a addAt(index,element) method that adds an element at a given index.
|
||||||
Just like how we remove elements at a given index, we need to keep track of the currentIndex as we traverse the linked list. When the currentIndex matches the given index, we would need to reassign the previous node's next property to reference the new added node. And the new node should reference the next node in the currentIndex.
|
Just like how we remove elements at a given index, we need to keep track of the currentIndex as we traverse the linked list. When the currentIndex matches the given index, we would need to reassign the previous node's next property to reference the new added node. And the new node should reference the next node in the currentIndex.
|
||||||
Returning to the conga line example, a new person wants to join the line, but he wants to join in the middle. You are in the middle of the line, so you take your hands off of the person ahead of you. The new person walks over and puts his hands on the person you once had hands on, and you now have your hands on the new person.
|
Returning to the conga line example, a new person wants to join the line, but he wants to join in the middle. You are in the middle of the line, so you take your hands off of the person ahead of you. The new person walks over and puts his hands on the person you once had hands on, and you now have your hands on the new person.
|
||||||
Instructions
|
|
||||||
Create an addAt(index,element) method that adds an element at a given index. Return false if an element was unable to be added.
|
|
||||||
Note
|
|
||||||
Remember to check if the given index is a negative or is longer than the length of the linked list.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Create an <code>addAt(index,element)</code> method that adds an element at a given index. Return false if an element could not be added.
|
||||||
|
<strong>Note:</strong> Remember to check if the given index is a negative or is longer than the length of the linked list.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -31,14 +28,11 @@ tests:
|
|||||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); test.addAt(0,'cat'); return test.size() === 3}()), 'Your <code>addAt</code> method should increase the length of the linked list by one for each new node added to the linked list.');
|
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); test.addAt(0,'cat'); return test.size() === 3}()), 'Your <code>addAt</code> method should increase the length of the linked list by one for each new node added to the linked list.');
|
||||||
- text: Your <code>addAt</code> method should return <code>false</code> if a node was unable to be added.
|
- text: Your <code>addAt</code> method should return <code>false</code> if a node was unable to be added.
|
||||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); return (test.addAt(4,'cat') === false); }()), 'Your <code>addAt</code> method should return <code>false</code> if a node was unable to be added.');
|
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); return (test.addAt(4,'cat') === false); }()), 'Your <code>addAt</code> method should return <code>false</code> if a node was unable to be added.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -46,23 +40,23 @@ function LinkedList() {
|
|||||||
var length = 0;
|
var length = 0;
|
||||||
var head = null;
|
var head = null;
|
||||||
|
|
||||||
var Node = function(element){
|
var Node = function(element) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.next = null;
|
this.next = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.size = function(){
|
this.size = function() {
|
||||||
return length;
|
return length;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.head = function(){
|
this.head = function() {
|
||||||
return head;
|
return head;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.add = function(element){
|
this.add = function(element) {
|
||||||
var node = new Node(element);
|
var node = new Node(element);
|
||||||
if (head === null){
|
if (head === null) {
|
||||||
head = node;
|
head = node;
|
||||||
} else {
|
} else {
|
||||||
var currentNode = head;
|
var currentNode = head;
|
||||||
|
|
||||||
@ -78,14 +72,9 @@ function LinkedList() {
|
|||||||
// Only change code below this line
|
// Only change code below this line
|
||||||
|
|
||||||
// Only change code above this line
|
// Only change code above this line
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -50,35 +50,29 @@ tests:
|
|||||||
testString: assert(undirectedAdjList.Jill.indexOf("Jenny") !== -1 && undirectedAdjList.Jill.indexOf("Jenny") !== -1, 'There should be an edge between <code>Jill</code> and <code>Jenny</code>.');
|
testString: assert(undirectedAdjList.Jill.indexOf("Jenny") !== -1 && undirectedAdjList.Jill.indexOf("Jenny") !== -1, 'There should be an edge between <code>Jill</code> and <code>Jenny</code>.');
|
||||||
- text: There should be an edge between <code>Jeff</code> and <code>Jenny</code>.
|
- text: There should be an edge between <code>Jeff</code> and <code>Jenny</code>.
|
||||||
testString: assert(undirectedAdjList.Jeff.indexOf("Jenny") !== -1 && undirectedAdjList.Jenny.indexOf("Jeff") !== -1, 'There should be an edge between <code>Jeff</code> and <code>Jenny</code>.');
|
testString: assert(undirectedAdjList.Jeff.indexOf("Jenny") !== -1 && undirectedAdjList.Jenny.indexOf("Jeff") !== -1, 'There should be an edge between <code>Jeff</code> and <code>Jenny</code>.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var undirectedAdjList = {
|
var undirectedAdjList = {};
|
||||||
};
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var undirectedAdjList = {
|
var undirectedAdjList = {
|
||||||
"James": ["Jeff"],"Jill": ["Jenny"],"Jenny": ["Jill", "Jeff"],
|
James: ['Jeff'],
|
||||||
"Jeff": ["James", "Jenny"]
|
Jill: ['Jenny'],
|
||||||
|
Jenny: ['Jill', 'Jeff'],
|
||||||
|
Jeff: ['James', 'Jenny']
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -54,33 +54,30 @@ tests:
|
|||||||
testString: assert((adjMatUndirected[2][4] === 1) && (adjMatUndirected[4][2] === 1), 'There should be an edge between the third and fifth node.');
|
testString: assert((adjMatUndirected[2][4] === 1) && (adjMatUndirected[4][2] === 1), 'There should be an edge between the third and fifth node.');
|
||||||
- text: There should be an edge between the fourth and fifth node.
|
- text: There should be an edge between the fourth and fifth node.
|
||||||
testString: assert((adjMatUndirected[3][4] === 1) && (adjMatUndirected[4][3] === 1), 'There should be an edge between the fourth and fifth node.');
|
testString: assert((adjMatUndirected[3][4] === 1) && (adjMatUndirected[4][3] === 1), 'There should be an edge between the fourth and fifth node.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var adjMatUndirected = [
|
var adjMatUndirected = [];
|
||||||
];
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var adjMatUndirected = [[0, 0, 1, 1, 0],[0, 0, 0, 0, 0],[1, 0, 0, 0, 1],[1, 0, 0, 0, 1],[0, 0, 1, 1, 0]];
|
var adjMatUndirected = [
|
||||||
|
[0, 0, 1, 1, 0],
|
||||||
|
[0, 0, 0, 0, 0],
|
||||||
|
[1, 0, 0, 0, 1],
|
||||||
|
[1, 0, 0, 0, 1],
|
||||||
|
[0, 0, 1, 1, 0]
|
||||||
|
];
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -8,12 +8,11 @@ challengeType: 1
|
|||||||
<section id='description'>
|
<section id='description'>
|
||||||
Now that we have a general sense of what a binary search tree is let's talk about it in a little more detail. Binary search trees provide logarithmic time for the common operations of lookup, insertion, and deletion in the average case, and linear time in the worst case. Why is this? Each of those basic operations requires us to find an item in the tree (or in the case of insertion to find where it should go) and because of the tree structure at each parent node we are branching left or right and effectively excluding half the size of the remaining tree. This makes the search proportional to the logarithm of the number of nodes in the tree, which creates logarithmic time for these operations in the average case.
|
Now that we have a general sense of what a binary search tree is let's talk about it in a little more detail. Binary search trees provide logarithmic time for the common operations of lookup, insertion, and deletion in the average case, and linear time in the worst case. Why is this? Each of those basic operations requires us to find an item in the tree (or in the case of insertion to find where it should go) and because of the tree structure at each parent node we are branching left or right and effectively excluding half the size of the remaining tree. This makes the search proportional to the logarithm of the number of nodes in the tree, which creates logarithmic time for these operations in the average case.
|
||||||
Ok, but what about the worst case? Well, consider constructing a tree from the following values, adding them left to right: <code>10</code>, <code>12</code>, <code>17</code>, <code>25</code>. Following our rules for a binary search tree, we will add <code>12</code> to the right of <code>10</code>, <code>17</code> to the right of this, and <code>25</code> to the right of this. Now our tree resembles a linked list and traversing it to find <code>25</code> would require us to traverse all the items in linear fashion. Hence, linear time in the worst case. The problem here is that the tree is unbalanced. We'll look a little more into what this means in the following challenges.
|
Ok, but what about the worst case? Well, consider constructing a tree from the following values, adding them left to right: <code>10</code>, <code>12</code>, <code>17</code>, <code>25</code>. Following our rules for a binary search tree, we will add <code>12</code> to the right of <code>10</code>, <code>17</code> to the right of this, and <code>25</code> to the right of this. Now our tree resembles a linked list and traversing it to find <code>25</code> would require us to traverse all the items in linear fashion. Hence, linear time in the worst case. The problem here is that the tree is unbalanced. We'll look a little more into what this means in the following challenges.
|
||||||
Instructions: In this challenge, we will create a utility for our tree. Write a method <code>isPresent</code> which takes an integer value as input and returns a boolean value for the presence or absence of that value in the binary search tree.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
In this challenge, we will create a utility for our tree. Write a method <code>isPresent</code> which takes an integer value as input and returns a boolean value for the presence or absence of that value in the binary search tree.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -29,9 +28,7 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.isPresent !== 'function') { return false; }; test.add(4); test.add(7); test.add(411); test.add(452); return ( test.isPresent(452) && test.isPresent(411) && test.isPresent(7) && !test.isPresent(100) ); })(), 'The <code>isPresent</code> method correctly checks for the presence or absence of elements added to the tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.isPresent !== 'function') { return false; }; test.add(4); test.add(7); test.add(411); test.add(452); return ( test.isPresent(452) && test.isPresent(411) && test.isPresent(7) && !test.isPresent(100) ); })(), 'The <code>isPresent</code> method correctly checks for the presence or absence of elements added to the tree.');
|
||||||
- text: <code>isPresent</code> handles cases where the tree is empty.
|
- text: <code>isPresent</code> handles cases where the tree is empty.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.isPresent !== 'function') { return false; }; return test.isPresent(5) == false; })(), '<code>isPresent</code> handles cases where the tree is empty.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.isPresent !== 'function') { return false; }; return test.isPresent(5) == false; })(), '<code>isPresent</code> handles cases where the tree is empty.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
@ -40,60 +37,59 @@ tests:
|
|||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// change code below this line
|
// change code below this line
|
||||||
// change code above this line
|
// change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
|
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
function searchTree(node) {
|
||||||
|
if (value < node.value) {
|
||||||
|
if (node.left == null) {
|
||||||
|
node.left = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.left != null) {
|
||||||
|
return searchTree(node.left);
|
||||||
|
}
|
||||||
|
} else if (value > node.value) {
|
||||||
|
if (node.right == null) {
|
||||||
|
node.right = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.right != null) {
|
||||||
|
return searchTree(node.right);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
return null;
|
||||||
if (value < node.value) {
|
}
|
||||||
if (node.left == null) {
|
}
|
||||||
node.left = new Node(value);
|
return searchTree(node);
|
||||||
return;
|
|
||||||
} else if (node.left != null) {
|
|
||||||
return searchTree(node.left)
|
|
||||||
};
|
|
||||||
} else if (value > node.value) {
|
|
||||||
if (node.right == null) {
|
|
||||||
node.right = new Node(value);
|
|
||||||
return;
|
|
||||||
} else if (node.right != null) {
|
|
||||||
return searchTree(node.right);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -43,10 +43,8 @@ This approach requires a constant amount of memory but allows files of a much la
|
|||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
|
||||||
In this challenge we will implement a circular queue. The circular queue should provide `enqueue` and `dequeue` methods which allow you to read from and write to the queue. The class itself should also accept an integer argument which you can use to specify the size of the queue when created. We've written the starting version of this class for you in the code editor. When you enqueue items to the queue, the write pointer should advance forward and loop back to the beginning once it reaches the end of the queue. Likewise, the read pointer should advance forward as you dequeue items. The write pointer should not be allowed to move past the read pointer (our class won't let you overwrite data you haven't read yet) and the read pointer should not be able to advance past data you have written.
|
In this challenge we will implement a circular queue. The circular queue should provide `enqueue` and `dequeue` methods which allow you to read from and write to the queue. The class itself should also accept an integer argument which you can use to specify the size of the queue when created. We've written the starting version of this class for you in the code editor. When you enqueue items to the queue, the write pointer should advance forward and loop back to the beginning once it reaches the end of the queue. Likewise, the read pointer should advance forward as you dequeue items. The write pointer should not be allowed to move past the read pointer (our class won't let you overwrite data you haven't read yet) and the read pointer should not be able to advance past data you have written.
|
||||||
In addition, the `enqueue` method should return the item you enqueued if it is successful; otherwise it will return `null`. Similarly, when you dequeue an item, that item should be returned and if you cannot dequeue an item you should return `null`.
|
In addition, the `enqueue` method should return the item you enqueued if it is successful; otherwise it will return `null`. Similarly, when you dequeue an item, that item should be returned and if you cannot dequeue an item you should return `null`.
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -71,7 +69,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -108,9 +105,6 @@ class CircularQueue {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -165,5 +159,4 @@ class CircularQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -44,7 +44,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -101,7 +100,6 @@ DoublyLinkedList.prototype = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -9,13 +9,12 @@ challengeType: 1
|
|||||||
In this challenge we will learn about hash tables. A Hash table is used to implement associative arrays, or mappings of key-value pairs, like the objects and Maps we have just been studying. A JavaScript object could be implemented as a hash table, for instance (its actual implementation will depend on the environment it's running in). The way a hash table works is that it takes a key input and hashes this key in a deterministic way to some numerical value. This numerical value is then used as the actual key the associated value is stored by. Then, if you try to access the same key again, the hashing function will process the key, return the same numerical result, which will then be used to look up the associated value. This provides very efficient O(n) lookup time on average.
|
In this challenge we will learn about hash tables. A Hash table is used to implement associative arrays, or mappings of key-value pairs, like the objects and Maps we have just been studying. A JavaScript object could be implemented as a hash table, for instance (its actual implementation will depend on the environment it's running in). The way a hash table works is that it takes a key input and hashes this key in a deterministic way to some numerical value. This numerical value is then used as the actual key the associated value is stored by. Then, if you try to access the same key again, the hashing function will process the key, return the same numerical result, which will then be used to look up the associated value. This provides very efficient O(n) lookup time on average.
|
||||||
Hash tables can be implemented as arrays with hash functions producing array indices within a specified range. In this method, the choice of the array size is important, as is the hashing function. For instance, what if the hashing function produces the same value for two different keys? This is called a collision. One way to handle collisions is to just store both key-value pairs at that index. Then, upon lookup of either, you would have to iterate through the bucket of items to find the key you are looking for. A good hashing function will minimize collisions to maintain efficient search time.
|
Hash tables can be implemented as arrays with hash functions producing array indices within a specified range. In this method, the choice of the array size is important, as is the hashing function. For instance, what if the hashing function produces the same value for two different keys? This is called a collision. One way to handle collisions is to just store both key-value pairs at that index. Then, upon lookup of either, you would have to iterate through the bucket of items to find the key you are looking for. A good hashing function will minimize collisions to maintain efficient search time.
|
||||||
Here, we won't be concerned with the details of hashing or hash table implementation, we will just try to get a general sense of how they work.
|
Here, we won't be concerned with the details of hashing or hash table implementation, we will just try to get a general sense of how they work.
|
||||||
Instructions: Let's create the basic functionality of a hash table. We've created a naive hashing function for you to use. You can pass a string value to the function hash and it will return a hashed value you can use as a key for storage. Store items based on this hashed value in the this.collection object. Create these three methods: add, remove, and lookup. The first should accept a key value pair to add to the hash table. The second should remove a key-value pair when passed a key. The third should accept a key and return the associated value or null if the key is not present.
|
|
||||||
Be sure to write your code to account for collisions!
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Let's create the basic functionality of a hash table. We've created a naive hashing function for you to use. You can pass a string value to the function <code>hash</code> and it will return a hashed value you can use as a key for storage. Store items based on this hashed value in the <code>this.collection</code> object. Create these three methods: <code>add</code>, <code>remove</code>, and <code>lookup</code>. The first should accept a key value pair to add to the hash table. The second should remove a key-value pair when passed a key. The third should accept a key and return the associated value or <code>null</code> if the key is not present.
|
||||||
|
Be sure to write your code to account for collisions!
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -39,23 +38,23 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; called = 0; test.add('key1','value1'); test.add('key2','value2'); test.add('key3','value3'); return (called === 3)})(), 'Items are added using the hash function.');
|
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; called = 0; test.add('key1','value1'); test.add('key2','value2'); test.add('key3','value3'); return (called === 3)})(), 'Items are added using the hash function.');
|
||||||
- text: The hash table handles collisions.
|
- text: The hash table handles collisions.
|
||||||
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; called = 0; test.add('key1','value1'); test.add('1key','value2'); test.add('ke1y','value3'); return (test.lookup('key1') === 'value1' && test.lookup('1key') == 'value2' && test.lookup('ke1y') == 'value3')})(), 'The hash table handles collisions.');
|
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; called = 0; test.add('key1','value1'); test.add('1key','value2'); test.add('ke1y','value3'); return (test.lookup('key1') === 'value1' && test.lookup('1key') == 'value2' && test.lookup('ke1y') == 'value3')})(), 'The hash table handles collisions.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var called = 0;
|
var called = 0;
|
||||||
var hash = (string) => {
|
var hash = string => {
|
||||||
called++;
|
called++;
|
||||||
var hash = 0;
|
var hashed = 0;
|
||||||
for (var i = 0; i < string.length; i++) { hash += string.charCodeAt(i); }
|
for (var i = 0; i < string.length; i++) {
|
||||||
return hash;
|
hashed += string.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return hashed;
|
||||||
};
|
};
|
||||||
var HashTable = function() {
|
var HashTable = function() {
|
||||||
this.collection = {};
|
this.collection = {};
|
||||||
@ -70,18 +69,18 @@ var HashTable = function() {
|
|||||||
<div id='js-setup'>
|
<div id='js-setup'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var called = 0;
|
var called = 0;
|
||||||
var hash = (string) => {
|
var hash = string => {
|
||||||
called++;
|
called++;
|
||||||
var hash = 0;
|
var hash = 0;
|
||||||
for (var i = 0; i < string.length; i++) { hash += string.charCodeAt(i); };
|
for (var i = 0; i < string.length; i++) {
|
||||||
return hash;
|
hash += string.charCodeAt(i);
|
||||||
};
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -90,4 +89,5 @@ var HashTable = function() {
|
|||||||
```js
|
```js
|
||||||
// solution required
|
// solution required
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -7,7 +7,11 @@ challengeType: 1
|
|||||||
## Description
|
## Description
|
||||||
<section id='description'>
|
<section id='description'>
|
||||||
The next few challenges will cover maps and hash tables. Maps are data structures that store key-value pairs. In JavaScript, these are available to us as objects. Maps provide rapid lookup of stored items based on key values and are very common and useful data structures.
|
The next few challenges will cover maps and hash tables. Maps are data structures that store key-value pairs. In JavaScript, these are available to us as objects. Maps provide rapid lookup of stored items based on key values and are very common and useful data structures.
|
||||||
Instructions: Let's get some practice creating our own map. Because JavaScript objects provide a much more efficient map structure than anything we could write here, this is intended primarily as a learning exercise. However, JavaScript objects only provide us with certain operations. What if we wanted to define custom operations?
|
</section>
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
<section id='instructions'>
|
||||||
|
Let's get some practice creating our own map. Because JavaScript objects provide a much more efficient map structure than anything we could write here, this is intended primarily as a learning exercise. However, JavaScript objects only provide us with certain operations. What if we wanted to define custom operations?
|
||||||
Use the <code>Map</code> object provided here as a wrapper around a JavaScript <code>object</code>. Create the following methods and operations on the Map object:
|
Use the <code>Map</code> object provided here as a wrapper around a JavaScript <code>object</code>. Create the following methods and operations on the Map object:
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>add</code> accepts a <code>key, value</code> pair to add to the map.</li>
|
<li><code>add</code> accepts a <code>key, value</code> pair to add to the map.</li>
|
||||||
@ -20,11 +24,6 @@ Use the <code>Map</code> object provided here as a wrapper around a JavaScript <
|
|||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
|
||||||
<section id='instructions'>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
<section id='tests'>
|
<section id='tests'>
|
||||||
|
|
||||||
@ -33,7 +32,7 @@ tests:
|
|||||||
- text: The Map data structure exists.
|
- text: The Map data structure exists.
|
||||||
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; return (typeof test == 'object')})(), 'The Map data structure exists.');
|
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; return (typeof test == 'object')})(), 'The Map data structure exists.');
|
||||||
- text: 'The Map object has the following methods: add, remove, get, has, values, clear, and size.'
|
- text: 'The Map object has the following methods: add, remove, get, has, values, clear, and size.'
|
||||||
testString: 'assert((function() { var test = false; if (typeof Map !== ''undefined'') { test = new Map() }; return (typeof test.add == ''function'' && typeof test.remove == ''function'' && typeof test.get == ''function'' && typeof test.has == ''function'' && typeof test.values == ''function'' && typeof test.clear == ''function'' && typeof test.size == ''function'')})(), ''The Map object has the following methods: add, remove, get, has, values, clear, and size.'');'
|
testString: "assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; return (typeof test.add == 'function' && typeof test.remove == 'function' && typeof test.get == 'function' && typeof test.has == 'function' && typeof test.values == 'function' && typeof test.clear == 'function' && typeof test.size == 'function')})(), 'The Map object has the following methods: add, remove, get, has, values, clear, and size.');"
|
||||||
- text: The add method adds items to the map.
|
- text: The add method adds items to the map.
|
||||||
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add(5,6); test.add(2,3); test.add(2,5); return (test.size() == 2)})(), 'The add method adds items to the map.');
|
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add(5,6); test.add(2,3); test.add(2,5); return (test.size() == 2)})(), 'The add method adds items to the map.');
|
||||||
- text: The has method returns true for added items and false for absent items.
|
- text: The has method returns true for added items and false for absent items.
|
||||||
@ -44,9 +43,7 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add('a','b'); test.add('c','d'); test.add('e','f'); var vals = test.values(); return (vals.indexOf('b') != -1 && vals.indexOf('d') != -1 && vals.indexOf('f') != -1)})(), 'The values method returns all the values stored in the map as strings in an array.');
|
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add('a','b'); test.add('c','d'); test.add('e','f'); var vals = test.values(); return (vals.indexOf('b') != -1 && vals.indexOf('d') != -1 && vals.indexOf('f') != -1)})(), 'The values method returns all the values stored in the map as strings in an array.');
|
||||||
- text: The clear method empties the map and the size method returns the number of items present in the map.
|
- text: The clear method empties the map and the size method returns the number of items present in the map.
|
||||||
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add('b','b'); test.add('c','d'); test.remove('asdfas'); var init = test.size(); test.clear(); return (init == 2 && test.size() == 0)})(), 'The clear method empties the map and the size method returns the number of items present in the map.');
|
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add('b','b'); test.add('c','d'); test.remove('asdfas'); var init = test.size(); test.clear(); return (init == 2 && test.size() == 0)})(), 'The clear method empties the map and the size method returns the number of items present in the map.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
@ -63,9 +60,6 @@ var Map = function() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -46,7 +46,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -9,13 +9,11 @@ challengeType: 1
|
|||||||
Like stacks, queues are a collection of elements. But unlike stacks, queues follow the FIFO (First-In First-Out) principle. Elements added to a queue are pushed to the tail, or the end, of the queue, and only the element at the front of the queue is allowed to be removed.
|
Like stacks, queues are a collection of elements. But unlike stacks, queues follow the FIFO (First-In First-Out) principle. Elements added to a queue are pushed to the tail, or the end, of the queue, and only the element at the front of the queue is allowed to be removed.
|
||||||
We could use an array to represent a queue, but just like stacks, we want to limit the amount of control we have over our queues.
|
We could use an array to represent a queue, but just like stacks, we want to limit the amount of control we have over our queues.
|
||||||
The two main methods of a queue class is the enqueue and the dequeue method. The enqueue method pushes an element to the tail of the queue, and the dequeue method removes and returns the element at the front of the queue. Other useful methods are the front, size, and isEmpty methods.
|
The two main methods of a queue class is the enqueue and the dequeue method. The enqueue method pushes an element to the tail of the queue, and the dequeue method removes and returns the element at the front of the queue. Other useful methods are the front, size, and isEmpty methods.
|
||||||
Instructions
|
|
||||||
Write an enqueue method that pushes an element to the tail of the queue, a dequeue method that removes and returns the front element, a front method that lets us see the front element, a size method that shows the length, and an isEmpty method to check if the queue is empty.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Write an <code>enqueue</code> method that pushes an element to the tail of the queue, a <code>dequeue</code> method that removes and returns the front element, a <code>front</code> method that lets us see the front element, a <code>size</code> method that shows the length, and an <code>isEmpty</code> method to check if the queue is empty.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -41,32 +39,29 @@ tests:
|
|||||||
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); return (test.size() === 1)}()), 'The <code>size</code> method should return the length of the queue');
|
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); return (test.size() === 1)}()), 'The <code>size</code> method should return the length of the queue');
|
||||||
- text: The <code>isEmpty</code> method should return <code>false</code> if there are elements in the queue
|
- text: The <code>isEmpty</code> method should return <code>false</code> if there are elements in the queue
|
||||||
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); return !(test.isEmpty())}()), 'The <code>isEmpty</code> method should return <code>false</code> if there are elements in the queue');
|
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); return !(test.isEmpty())}()), 'The <code>isEmpty</code> method should return <code>false</code> if there are elements in the queue');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
|
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function Queue () {
|
function Queue() {
|
||||||
var collection = [];
|
var collection = [];
|
||||||
this.print = function() {
|
this.print = function() {
|
||||||
console.log(collection);
|
console.log(collection);
|
||||||
};
|
};
|
||||||
// Only change code below this line
|
// Only change code below this line
|
||||||
|
|
||||||
// Only change code above this line
|
// Only change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -63,7 +63,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -93,8 +92,6 @@ class Set {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -133,5 +130,4 @@ class Set {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -9,14 +9,12 @@ challengeType: 1
|
|||||||
In the last section, we talked about what a stack is and how we can use an array to represent a stack. In this section, we will be creating our own stack class.
|
In the last section, we talked about what a stack is and how we can use an array to represent a stack. In this section, we will be creating our own stack class.
|
||||||
Although you can use arrays to create stacks, sometimes it is best to limit the amount of control we have with our stacks.
|
Although you can use arrays to create stacks, sometimes it is best to limit the amount of control we have with our stacks.
|
||||||
Apart from the <code>push</code> and <code>pop</code> method, stacks have other useful methods. Let's add a <code>peek</code>, <code>isEmpty</code>, and <code>clear</code> method to our stack class.
|
Apart from the <code>push</code> and <code>pop</code> method, stacks have other useful methods. Let's add a <code>peek</code>, <code>isEmpty</code>, and <code>clear</code> method to our stack class.
|
||||||
Instructions
|
|
||||||
Write a <code>push</code> method that pushes an element to the top of the stack, a <code>pop</code> method that removes the element on the top of the stack, a <code>peek</code> method that looks at the first element in the stack, an <code>isEmpty</code> method that checks if the stack is empty, and a <code>clear</code> method that removes all elements from the stack.
|
|
||||||
Normally stacks don't have this, but we've added a <code>print</code> helper method that console logs the collection.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Write a <code>push</code> method that pushes an element to the top of the stack, a <code>pop</code> method that removes the element on the top of the stack, a <code>peek</code> method that looks at the first element in the stack, an <code>isEmpty</code> method that checks if the stack is empty, and a <code>clear</code> method that removes all elements from the stack.
|
||||||
|
Normally stacks don't have this, but we've added a <code>print</code> helper method that console logs the collection.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -42,32 +40,25 @@ tests:
|
|||||||
testString: assert((function(){var test = new Stack(); return test.isEmpty()}()), 'The <code>isEmpty</code> method should return true if a stack does not contain any elements');
|
testString: assert((function(){var test = new Stack(); return test.isEmpty()}()), 'The <code>isEmpty</code> method should return true if a stack does not contain any elements');
|
||||||
- text: The <code>clear</code> method should remove all element from the stack
|
- text: The <code>clear</code> method should remove all element from the stack
|
||||||
testString: assert((function(){var test = new Stack(); test.push('CS50'); test.clear(); return (test.isEmpty())}()), 'The <code>clear</code> method should remove all element from the stack');
|
testString: assert((function(){var test = new Stack(); test.push('CS50'); test.clear(); return (test.isEmpty())}()), 'The <code>clear</code> method should remove all element from the stack');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function Stack() {
|
function Stack() {
|
||||||
var collection = [];
|
var collection = [];
|
||||||
this.print = function() {
|
this.print = function() {
|
||||||
console.log(collection);
|
console.log(collection);
|
||||||
};
|
};
|
||||||
// Only change code below this line
|
// Only change code below this line
|
||||||
|
|
||||||
// Only change code above this line
|
// Only change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -75,27 +66,27 @@ function Stack() {
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
class Stack {
|
class Stack {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.collection = [];
|
this.collection = [];
|
||||||
}
|
}
|
||||||
print(){
|
print() {
|
||||||
console.log(this.collection);
|
console.log(this.collection);
|
||||||
}
|
}
|
||||||
push(val){
|
push(val) {
|
||||||
this.collection.push(val);
|
this.collection.push(val);
|
||||||
}
|
}
|
||||||
pop(){
|
pop() {
|
||||||
return this.collection.pop();
|
return this.collection.pop();
|
||||||
}
|
}
|
||||||
peek(){
|
peek() {
|
||||||
return this.collection[this.collection.length-1];
|
return this.collection[this.collection.length - 1];
|
||||||
}
|
}
|
||||||
isEmpty(){
|
isEmpty() {
|
||||||
return this.collection.length === 0;
|
return this.collection.length === 0;
|
||||||
}
|
}
|
||||||
clear(){
|
clear() {
|
||||||
return this.collection.length = 0;
|
return (this.collection.length = 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</section>
|
</section>
|
||||||
|
@ -9,13 +9,12 @@ challengeType: 1
|
|||||||
Here we will move on from binary search trees and take a look at another type of tree structure called a trie. A trie is an ordered search tree commonly used to hold strings, or more generically associative arrays or dynamic datasets in which the keys are strings. They are very good at storing sets of data when many keys will have overlapping prefixes, for example, all the words in a dictionary.
|
Here we will move on from binary search trees and take a look at another type of tree structure called a trie. A trie is an ordered search tree commonly used to hold strings, or more generically associative arrays or dynamic datasets in which the keys are strings. They are very good at storing sets of data when many keys will have overlapping prefixes, for example, all the words in a dictionary.
|
||||||
Unlike a binary tree, nodes are not associated with actual values. Instead, the path to a node represents a specific key. For instance, if we wanted to store the string code in a trie, we would have four nodes, one for each letter: c — o — d — e. Following that path through all these nodes will then create code as a string — that path is the key we stored. Then, if we wanted to add the string coding, it would share the first three nodes of code before branching away after the d. In this way, large datasets can be stored very compactly. In addition, search can be very quick because it is effectively limited to the length of the string you are storing. Furthermore, unlike binary trees a node can store any number of child nodes.
|
Unlike a binary tree, nodes are not associated with actual values. Instead, the path to a node represents a specific key. For instance, if we wanted to store the string code in a trie, we would have four nodes, one for each letter: c — o — d — e. Following that path through all these nodes will then create code as a string — that path is the key we stored. Then, if we wanted to add the string coding, it would share the first three nodes of code before branching away after the d. In this way, large datasets can be stored very compactly. In addition, search can be very quick because it is effectively limited to the length of the string you are storing. Furthermore, unlike binary trees a node can store any number of child nodes.
|
||||||
As you might have guessed from the above example, some metadata is commonly stored at nodes that hold the end of a key so that on later traversals that key can still be retrieved. For instance, if we added codes in our example above we would need some way to know that the e in code represents the end of a key that was previously entered. Otherwise, this information would effectively be lost when we add codes.
|
As you might have guessed from the above example, some metadata is commonly stored at nodes that hold the end of a key so that on later traversals that key can still be retrieved. For instance, if we added codes in our example above we would need some way to know that the e in code represents the end of a key that was previously entered. Otherwise, this information would effectively be lost when we add codes.
|
||||||
Instructions: Let's create a trie to store words. It will accept words through an add method and store these in a trie data structure. It will also allow us to query if a given string is a word with an isWord method, and retrieve all the words entered into the trie with a print method. isWord should return a boolean value and print should return an array of all these words as string values.
|
|
||||||
In order for us to verify that this data structure is implemented correctly, we've provided a Node structure for each node in the tree. Each node will be an object with a keys property which is a JavaScript Map object. This will hold the individual letters that are valid keys of each node. We've also created an end property on the nodes that can be set to true if the node represents the termination of a word.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Let's create a trie to store words. It will accept words through an <code>add</code> method and store these in a trie data structure. It will also allow us to query if a given string is a word with an <code>isWord</code> method, and retrieve all the words entered into the trie with a <code>print</code> method. <code>isWord</code> should return a boolean value and print should return an array of all these words as string values.
|
||||||
|
In order for us to verify that this data structure is implemented correctly, we've provided a <code>Node</code> structure for each node in the tree. Each node will be an object with a <code>keys</code> property which is a JavaScript Map object. This will hold the individual letters that are valid keys of each node. We've also created an <code>end</code> property on the nodes that can be set to <code>true</code> if the node represents the termination of a word.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -33,18 +32,16 @@ tests:
|
|||||||
testString: assert((function testTrie() { var test = false; if (typeof Trie !== 'undefined') { test = new Trie() } else { return false; }; test.add('jump'); test.add('jumps'); test.add('jumped'); test.add('house'); test.add('mouse'); var added = test.print(); return (added.indexOf('jump') != -1 && added.indexOf('jumps') != -1 && added.indexOf('jumped') != -1 && added.indexOf('house') != -1 && added.indexOf('mouse') != -1 && added.length == 5); }()), 'The print method returns all items added to the trie as strings in an array.');
|
testString: assert((function testTrie() { var test = false; if (typeof Trie !== 'undefined') { test = new Trie() } else { return false; }; test.add('jump'); test.add('jumps'); test.add('jumped'); test.add('house'); test.add('mouse'); var added = test.print(); return (added.indexOf('jump') != -1 && added.indexOf('jumps') != -1 && added.indexOf('jumped') != -1 && added.indexOf('house') != -1 && added.indexOf('mouse') != -1 && added.length == 5); }()), 'The print method returns all items added to the trie as strings in an array.');
|
||||||
- text: The isWord method returns true only for words added to the trie and false for all other words.
|
- text: The isWord method returns true only for words added to the trie and false for all other words.
|
||||||
testString: assert((function testTrie() { var test = false; if (typeof Trie !== 'undefined') { test = new Trie() } else { return false; }; test.add('hop'); test.add('hops'); test.add('hopped'); test.add('hoppy'); test.add('hope'); return (test.isWord('hop') && !test.isWord('ho') && test.isWord('hopped') && !test.isWord('hopp') && test.isWord('hoppy') && !test.isWord('hoping')); }()), 'The isWord method returns true only for words added to the trie and false for all other words.');
|
testString: assert((function testTrie() { var test = false; if (typeof Trie !== 'undefined') { test = new Trie() } else { return false; }; test.add('hop'); test.add('hops'); test.add('hopped'); test.add('hoppy'); test.add('hope'); return (test.isWord('hop') && !test.isWord('ho') && test.isWord('hopped') && !test.isWord('hopp') && test.isWord('hoppy') && !test.isWord('hoping')); }()), 'The isWord method returns true only for words added to the trie and false for all other words.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
var Node = function() {
|
var Node = function() {
|
||||||
this.keys = new Map();
|
this.keys = new Map();
|
||||||
this.end = false;
|
this.end = false;
|
||||||
@ -60,11 +57,7 @@ var Trie = function() {
|
|||||||
// change code above this line
|
// change code above this line
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -14,12 +14,11 @@ The new version of JavaScript provides us with a built-in Map object which provi
|
|||||||
<code>.clear()</code> removes all key, value pairs
|
<code>.clear()</code> removes all key, value pairs
|
||||||
<code>.entries()</code> returns an array of all the keys in insertion order
|
<code>.entries()</code> returns an array of all the keys in insertion order
|
||||||
<code>.values()</code> returns an array of all the values in insertion order
|
<code>.values()</code> returns an array of all the values in insertion order
|
||||||
Instructions: Define a JavaScript Map object and assign to it a variable called myMap. Add the key, value pair <code>freeCodeCamp</code>, <code>Awesome!</code> to it.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Define a JavaScript Map object and assign to it a variable called myMap. Add the key, value pair <code>freeCodeCamp</code>, <code>Awesome!</code> to it.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -31,24 +30,17 @@ tests:
|
|||||||
testString: assert(typeof myMap === 'object', 'The myMap object exists.');
|
testString: assert(typeof myMap === 'object', 'The myMap object exists.');
|
||||||
- text: myMap contains the key value pair <code>freeCodeCamp</code>, <code>Awesome!</code>.
|
- text: myMap contains the key value pair <code>freeCodeCamp</code>, <code>Awesome!</code>.
|
||||||
testString: assert(myMap.get('freeCodeCamp') === 'Awesome!', 'myMap contains the key value pair <code>freeCodeCamp</code>, <code>Awesome!</code>.');
|
testString: assert(myMap.get('freeCodeCamp') === 'Awesome!', 'myMap contains the key value pair <code>freeCodeCamp</code>, <code>Awesome!</code>.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// change code below this line
|
// change code below this line
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -48,7 +48,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -5,19 +5,20 @@ challengeType: 1
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
<section id='description'>
|
<section id='description'>
|
||||||
This is the first of three challenges where we will implement a more difficult operation in binary search trees: deletion. Deletion is difficult because removing nodes breaks links in the tree. These links must be carefully reestablished to ensure the binary tree structure is maintained. For some deletions, this means the tree must be rearranged. In general, you will encounter one of three cases when trying to delete a node:
|
This is the first of three challenges where we will implement a more difficult operation in binary search trees: deletion. Deletion is difficult because removing nodes breaks links in the tree. These links must be carefully reestablished to ensure the binary tree structure is maintained. For some deletions, this means the tree must be rearranged. In general, you will encounter one of three cases when trying to delete a node:
|
||||||
Leaf Node: The target to delete has zero children.
|
Leaf Node: The target to delete has zero children.
|
||||||
One Child: The target to delete only has one child.
|
One Child: The target to delete only has one child.
|
||||||
Two Children: The target to delete has two child nodes.
|
Two Children: The target to delete has two child nodes.
|
||||||
Removing a leaf node is easy, we simply remove it. Deleting a node with one child is also relatively easy, we simply remove it and link its parent to child of the node we deleted. Removing a node with two children is more difficult, however, because this creates two child nodes that need to be reconnected to the parent tree. We'll see how to deal with this case in the third challenge. Additionally, you need to be mindful of some edge cases when handling deletion. What if the tree is empty? What if the node to delete is the root node? What if there are only two elements in the tree? For now, let's handle the first case where we delete a leaf node.
|
Removing a leaf node is easy, we simply remove it. Deleting a node with one child is also relatively easy, we simply remove it and link its parent to child of the node we deleted. Removing a node with two children is more difficult, however, because this creates two child nodes that need to be reconnected to the parent tree. We'll see how to deal with this case in the third challenge. Additionally, you need to be mindful of some edge cases when handling deletion. What if the tree is empty? What if the node to delete is the root node? What if there are only two elements in the tree? For now, let's handle the first case where we delete a leaf node.
|
||||||
Instructions: Create a method on our binary tree called <code>remove</code>. We'll build the logic for our deletion operation in here. First, you'll want to create a function within remove that finds the node we are trying to delete in the current tree. If the node is not present in the tree, <code>remove</code> should return <code>null</code>. Now, if the target node is a leaf node with no children, then the parent reference to it should be set to <code>null</code>. This effectively deletes the node from the tree. To do this, you will have to keep track of the parent of the node we are trying to delete as well. It will also be useful to create a way to track the number of children the target node has, as this will determine which case our deletion falls under.
|
|
||||||
We will handle the second and third cases in the next challenges. Good luck!
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
|
||||||
|
|
||||||
|
<section id='instructions'>
|
||||||
|
Create a method on our binary tree called <code>remove</code>. We'll build the logic for our deletion operation in here. First, you'll want to create a function within remove that finds the node we are trying to delete in the current tree. If the node is not present in the tree, <code>remove</code> should return <code>null</code>. Now, if the target node is a leaf node with no children, then the parent reference to it should be set to <code>null</code>. This effectively deletes the node from the tree. To do this, you will have to keep track of the parent of the node we are trying to delete as well. It will also be useful to create a way to track the number of children the target node has, as this will determine which case our deletion falls under.
|
||||||
|
We will handle the second and third cases in the next challenges. Good luck!
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -35,116 +36,111 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(500); test.remove(500); return (test.inorder() == null); })(), 'If the root node has no children, deleting it sets the root to <code>null</code>.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(500); test.remove(500); return (test.inorder() == null); })(), 'If the root node has no children, deleting it sets the root to <code>null</code>.');
|
||||||
- text: The <code>remove</code> method removes leaf nodes from the tree
|
- text: The <code>remove</code> method removes leaf nodes from the tree
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(5); test.add(3); test.add(7); test.add(6); test.add(10); test.add(12); test.remove(3); test.remove(12); test.remove(10); return (test.inorder().join('') == '567'); })(), 'The <code>remove</code> method removes leaf nodes from the tree');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(5); test.add(3); test.add(7); test.add(6); test.add(10); test.add(12); test.remove(3); test.remove(12); test.remove(10); return (test.inorder().join('') == '567'); })(), 'The <code>remove</code> method removes leaf nodes from the tree');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// case 1: target has no children, change code below this line
|
// case 1: target has no children, change code below this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
function searchTree(node) {
|
||||||
if (value < node.value) {
|
if (value < node.value) {
|
||||||
if (node.left == null) {
|
if (node.left == null) {
|
||||||
node.left = new Node(value);
|
node.left = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else if (node.left != null) {
|
} else if (node.left != null) {
|
||||||
return searchTree(node.left)
|
return searchTree(node.left);
|
||||||
};
|
}
|
||||||
} else if (value > node.value) {
|
} else if (value > node.value) {
|
||||||
if (node.right == null) {
|
if (node.right == null) {
|
||||||
node.right = new Node(value);
|
node.right = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else if (node.right != null) {
|
} else if (node.right != null) {
|
||||||
return searchTree(node.right);
|
return searchTree(node.right);
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
inorder: function() {
|
|
||||||
if (this.root == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
var result = new Array();
|
|
||||||
function traverseInOrder(node) {
|
|
||||||
if (node.left != null) {
|
|
||||||
traverseInOrder(node.left);
|
|
||||||
};
|
|
||||||
result.push(node.value);
|
|
||||||
if (node.right != null) {
|
|
||||||
traverseInOrder(node.right);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
traverseInOrder(this.root);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
isBinarySearchTree() {
|
|
||||||
if (this.root == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
} else {
|
||||||
var check = true;
|
return null;
|
||||||
function checkTree(node) {
|
|
||||||
if (node.left != null) {
|
|
||||||
var left = node.left;
|
|
||||||
if (left.value > node.value) {
|
|
||||||
check = false;
|
|
||||||
} else {
|
|
||||||
checkTree(left);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node.right != null) {
|
|
||||||
var right = node.right;
|
|
||||||
if (right.value < node.value) {
|
|
||||||
check = false;
|
|
||||||
} else {
|
|
||||||
checkTree(right);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
checkTree(this.root);
|
|
||||||
return check;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return searchTree(node);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
inorder: function() {
|
||||||
|
if (this.root == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
var result = new Array();
|
||||||
|
function traverseInOrder(node) {
|
||||||
|
if (node.left != null) {
|
||||||
|
traverseInOrder(node.left);
|
||||||
|
}
|
||||||
|
result.push(node.value);
|
||||||
|
if (node.right != null) {
|
||||||
|
traverseInOrder(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traverseInOrder(this.root);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isBinarySearchTree() {
|
||||||
|
if (this.root == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
var check = true;
|
||||||
|
function checkTree(node) {
|
||||||
|
if (node.left != null) {
|
||||||
|
var left = node.left;
|
||||||
|
if (left.value > node.value) {
|
||||||
|
check = false;
|
||||||
|
} else {
|
||||||
|
checkTree(left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.right != null) {
|
||||||
|
var right = node.right;
|
||||||
|
if (right.value < node.value) {
|
||||||
|
check = false;
|
||||||
|
} else {
|
||||||
|
checkTree(right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkTree(this.root);
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -7,12 +7,11 @@ challengeType: 1
|
|||||||
## Description
|
## Description
|
||||||
<section id='description'>
|
<section id='description'>
|
||||||
Now that we can delete leaf nodes let's move on to the second case: deleting a node with one child. For this case, say we have a tree with the following nodes 1 — 2 — 3 where 1 is the root. To delete 2, we simply need to make the right reference in 1 point to 3. More generally to delete a node with only one child, we make that node's parent reference the next node in the tree.
|
Now that we can delete leaf nodes let's move on to the second case: deleting a node with one child. For this case, say we have a tree with the following nodes 1 — 2 — 3 where 1 is the root. To delete 2, we simply need to make the right reference in 1 point to 3. More generally to delete a node with only one child, we make that node's parent reference the next node in the tree.
|
||||||
Instructions: We've provided some code in our <code>remove</code> method that accomplishes the tasks from the last challenge. We find the target to delete and its parent and define the number of children the target node has. Let's add the next case here for target nodes with only one child. Here, we'll have to determine if the single child is a left or right branch in the tree and then set the correct reference in the parent to point to this node. In addition, let's account for the case where the target is the root node (this means the parent node will be <code>null</code>). Feel free to replace all the starter code with your own as long as it passes the tests.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
We've provided some code in our <code>remove</code> method that accomplishes the tasks from the last challenge. We find the target to delete and its parent and define the number of children the target node has. Let's add the next case here for target nodes with only one child. Here, we'll have to determine if the single child is a left or right branch in the tree and then set the correct reference in the parent to point to this node. In addition, let's account for the case where the target is the root node (this means the parent node will be <code>null</code>). Feel free to replace all the starter code with your own as long as it passes the tests.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -34,18 +33,15 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(-1); test.add(3); test.add(7); test.add(16); test.remove(16); test.remove(7); test.remove(3); return (test.inorder().join('') == '-1'); })(), 'The <code>remove</code> method removes nodes with one child.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(-1); test.add(3); test.add(7); test.add(16); test.remove(16); test.remove(7); test.remove(3); return (test.inorder().join('') == '-1'); })(), 'The <code>remove</code> method removes nodes with one child.');
|
||||||
- text: Removing the root in a tree with two nodes sets the second to be the root.
|
- text: Removing the root in a tree with two nodes sets the second to be the root.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(15); test.add(27); test.remove(15); return (test.inorder().join('') == '27'); })(), 'Removing the root in a tree with two nodes sets the second to be the root.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(15); test.add(27); test.remove(15); return (test.inorder().join('') == '27'); })(), 'Removing the root in a tree with two nodes sets the second to be the root.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
@ -75,18 +71,18 @@ function BinarySearchTree() {
|
|||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}).bind(this)();
|
}.bind(this)());
|
||||||
if (target === null) {
|
if (target === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// count the children of the target to delete
|
// count the children of the target to delete
|
||||||
var children = (target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
|
var children =
|
||||||
|
(target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
|
||||||
// case 1: target has no children
|
// case 1: target has no children
|
||||||
if (children === 0) {
|
if (children === 0) {
|
||||||
if (target == this.root) {
|
if (target == this.root) {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (parent.left == target) {
|
if (parent.left == target) {
|
||||||
parent.left = null;
|
parent.left = null;
|
||||||
} else {
|
} else {
|
||||||
@ -101,90 +97,88 @@ function BinarySearchTree() {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
function searchTree(node) {
|
||||||
if (value < node.value) {
|
if (value < node.value) {
|
||||||
if (node.left == null) {
|
if (node.left == null) {
|
||||||
node.left = new Node(value);
|
node.left = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else if (node.left != null) {
|
} else if (node.left != null) {
|
||||||
return searchTree(node.left)
|
return searchTree(node.left);
|
||||||
};
|
}
|
||||||
} else if (value > node.value) {
|
} else if (value > node.value) {
|
||||||
if (node.right == null) {
|
if (node.right == null) {
|
||||||
node.right = new Node(value);
|
node.right = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else if (node.right != null) {
|
} else if (node.right != null) {
|
||||||
return searchTree(node.right);
|
return searchTree(node.right);
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
inorder: function() {
|
|
||||||
if (this.root == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
var result = new Array();
|
|
||||||
function traverseInOrder(node) {
|
|
||||||
if (node.left != null) {
|
|
||||||
traverseInOrder(node.left);
|
|
||||||
};
|
|
||||||
result.push(node.value);
|
|
||||||
if (node.right != null) {
|
|
||||||
traverseInOrder(node.right);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
traverseInOrder(this.root);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
isBinarySearchTree() {
|
|
||||||
if (this.root == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
} else {
|
||||||
var check = true;
|
return null;
|
||||||
function checkTree(node) {
|
|
||||||
if (node.left != null) {
|
|
||||||
var left = node.left;
|
|
||||||
if (left.value > node.value) {
|
|
||||||
check = false;
|
|
||||||
} else {
|
|
||||||
checkTree(left);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node.right != null) {
|
|
||||||
var right = node.right;
|
|
||||||
if (right.value < node.value) {
|
|
||||||
check = false;
|
|
||||||
} else {
|
|
||||||
checkTree(right);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
checkTree(this.root);
|
|
||||||
return check;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return searchTree(node);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
inorder: function() {
|
||||||
|
if (this.root == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
var result = new Array();
|
||||||
|
function traverseInOrder(node) {
|
||||||
|
if (node.left != null) {
|
||||||
|
traverseInOrder(node.left);
|
||||||
|
}
|
||||||
|
result.push(node.value);
|
||||||
|
if (node.right != null) {
|
||||||
|
traverseInOrder(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traverseInOrder(this.root);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isBinarySearchTree() {
|
||||||
|
if (this.root == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
var check = true;
|
||||||
|
function checkTree(node) {
|
||||||
|
if (node.left != null) {
|
||||||
|
var left = node.left;
|
||||||
|
if (left.value > node.value) {
|
||||||
|
check = false;
|
||||||
|
} else {
|
||||||
|
checkTree(left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.right != null) {
|
||||||
|
var right = node.right;
|
||||||
|
if (right.value < node.value) {
|
||||||
|
check = false;
|
||||||
|
} else {
|
||||||
|
checkTree(right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkTree(this.root);
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -8,12 +8,11 @@ challengeType: 1
|
|||||||
<section id='description'>
|
<section id='description'>
|
||||||
Removing nodes that have two children is the hardest case to implement. Removing a node like this produces two subtrees that are no longer connected to the original tree structure. How can we reconnect them? One method is to find the smallest value in the right subtree of the target node and replace the target node with this value. Selecting the replacement in this way ensures that it is greater than every node in the left subtree it becomes the new parent of but also less than every node in the right subtree it becomes the new parent of.
|
Removing nodes that have two children is the hardest case to implement. Removing a node like this produces two subtrees that are no longer connected to the original tree structure. How can we reconnect them? One method is to find the smallest value in the right subtree of the target node and replace the target node with this value. Selecting the replacement in this way ensures that it is greater than every node in the left subtree it becomes the new parent of but also less than every node in the right subtree it becomes the new parent of.
|
||||||
Once this replacement is made the replacement node must be removed from the right subtree. Even this operation is tricky because the replacement may be a leaf or it may itself be the parent of a right subtree. If it is a leaf we must remove its parent's reference to it. Otherwise, it must be the right child of the target. In this case, we must replace the target value with the replacement value and make the target reference the replacement's right child.
|
Once this replacement is made the replacement node must be removed from the right subtree. Even this operation is tricky because the replacement may be a leaf or it may itself be the parent of a right subtree. If it is a leaf we must remove its parent's reference to it. Otherwise, it must be the right child of the target. In this case, we must replace the target value with the replacement value and make the target reference the replacement's right child.
|
||||||
Instructions: Let's finish our <code>remove</code> method by handling the third case. We've provided some code again for the first two cases. Add some code now to handle target nodes with two children. Any edge cases to be aware of? What if the tree has only three nodes? Once you are finished this will complete our deletion operation for binary search trees. Nice job, this is a pretty hard problem!
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Let's finish our <code>remove</code> method by handling the third case. We've provided some code again for the first two cases. Add some code now to handle target nodes with two children. Any edge cases to be aware of? What if the tree has only three nodes? Once you are finished this will complete our deletion operation for binary search trees. Nice job, this is a pretty hard problem!
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -26,11 +25,11 @@ tests:
|
|||||||
- text: The binary search tree has a method called <code>remove</code>.
|
- text: The binary search tree has a method called <code>remove</code>.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.remove == 'function')})(), 'The binary search tree has a method called <code>remove</code>.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.remove == 'function')})(), 'The binary search tree has a method called <code>remove</code>.');
|
||||||
- text: Trying to remove an element that does not exist returns <code>null</code>.
|
- text: Trying to remove an element that does not exist returns <code>null</code>.
|
||||||
testString: 'assert((function() { var test = false; if (typeof BinarySearchTree !== ''undefined'') { test = new BinarySearchTree() } else { return false; }; return (typeof test.remove == ''function'') ? (test.remove(100) == null) : false})(), ''Trying to remove an element that does not exist returns <code>null</code>.'');'
|
testString: "assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.remove == 'function') ? (test.remove(100) == null) : false})(), 'Trying to remove an element that does not exist returns <code>null</code>.');"
|
||||||
- text: If the root node has no children, deleting it sets the root to <code>null</code>.
|
- text: If the root node has no children, deleting it sets the root to <code>null</code>.
|
||||||
testString: 'assert((function() { var test = false; if (typeof BinarySearchTree !== ''undefined'') { test = new BinarySearchTree() } else { return false; }; test.add(500); test.remove(500); return (typeof test.remove == ''function'') ? (test.inorder() == null) : false})(), ''If the root node has no children, deleting it sets the root to <code>null</code>.'');'
|
testString: "assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; test.add(500); test.remove(500); return (typeof test.remove == 'function') ? (test.inorder() == null) : false})(), 'If the root node has no children, deleting it sets the root to <code>null</code>.');"
|
||||||
- text: The <code>remove</code> method removes leaf nodes from the tree
|
- text: The <code>remove</code> method removes leaf nodes from the tree
|
||||||
testString: 'assert((function() { var test = false; if (typeof BinarySearchTree !== ''undefined'') { test = new BinarySearchTree() } else { return false; }; test.add(5); test.add(3); test.add(7); test.add(6); test.add(10); test.add(12); test.remove(3); test.remove(12); test.remove(10); return (typeof test.remove == ''function'') ? (test.inorder().join('''') == ''567'') : false})(), ''The <code>remove</code> method removes leaf nodes from the tree'');'
|
testString: "assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; test.add(5); test.add(3); test.add(7); test.add(6); test.add(10); test.add(12); test.remove(3); test.remove(12); test.remove(10); return (typeof test.remove == 'function') ? (test.inorder().join('') == '567') : false})(), 'The <code>remove</code> method removes leaf nodes from the tree');"
|
||||||
- text: The <code>remove</code> method removes nodes with one child.
|
- text: The <code>remove</code> method removes nodes with one child.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(-1); test.add(3); test.add(7); test.add(16); test.remove(16); test.remove(7); test.remove(3); return (test.inorder().join('') == '-1'); })(), 'The <code>remove</code> method removes nodes with one child.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(-1); test.add(3); test.add(7); test.add(16); test.remove(16); test.remove(7); test.remove(3); return (test.inorder().join('') == '-1'); })(), 'The <code>remove</code> method removes nodes with one child.');
|
||||||
- text: Removing the root in a tree with two nodes sets the second to be the root.
|
- text: Removing the root in a tree with two nodes sets the second to be the root.
|
||||||
@ -39,18 +38,15 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(1); test.add(4); test.add(3); test.add(7); test.add(9); test.add(11); test.add(14); test.add(15); test.add(19); test.add(50); test.remove(9); if (!test.isBinarySearchTree()) { return false; }; test.remove(11); if (!test.isBinarySearchTree()) { return false; }; test.remove(14); if (!test.isBinarySearchTree()) { return false; }; test.remove(19); if (!test.isBinarySearchTree()) { return false; }; test.remove(3); if (!test.isBinarySearchTree()) { return false; }; test.remove(50); if (!test.isBinarySearchTree()) { return false; }; test.remove(15); if (!test.isBinarySearchTree()) { return false; }; return (test.inorder().join('') == '147'); })(), 'The <code>remove</code> method removes nodes with two children while maintaining the binary search tree structure.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(1); test.add(4); test.add(3); test.add(7); test.add(9); test.add(11); test.add(14); test.add(15); test.add(19); test.add(50); test.remove(9); if (!test.isBinarySearchTree()) { return false; }; test.remove(11); if (!test.isBinarySearchTree()) { return false; }; test.remove(14); if (!test.isBinarySearchTree()) { return false; }; test.remove(19); if (!test.isBinarySearchTree()) { return false; }; test.remove(3); if (!test.isBinarySearchTree()) { return false; }; test.remove(50); if (!test.isBinarySearchTree()) { return false; }; test.remove(15); if (!test.isBinarySearchTree()) { return false; }; return (test.inorder().join('') == '147'); })(), 'The <code>remove</code> method removes nodes with two children while maintaining the binary search tree structure.');
|
||||||
- text: The root can be removed on a tree of three nodes.
|
- text: The root can be removed on a tree of three nodes.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(100); test.add(50); test.add(300); test.remove(100); return (test.inorder().join('') == 50300); })(), 'The root can be removed on a tree of three nodes.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.remove !== 'function') { return false; }; test.add(100); test.add(50); test.add(300); test.remove(100); return (test.inorder().join('') == 50300); })(), 'The root can be removed on a tree of three nodes.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
@ -80,18 +76,18 @@ function BinarySearchTree() {
|
|||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}).bind(this)();
|
}.bind(this)());
|
||||||
if (target === null) {
|
if (target === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// count the children of the target to delete
|
// count the children of the target to delete
|
||||||
var children = (target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
|
var children =
|
||||||
|
(target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
|
||||||
// case 1: target has no children
|
// case 1: target has no children
|
||||||
if (children === 0) {
|
if (children === 0) {
|
||||||
if (target == this.root) {
|
if (target == this.root) {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (parent.left == target) {
|
if (parent.left == target) {
|
||||||
parent.left = null;
|
parent.left = null;
|
||||||
} else {
|
} else {
|
||||||
@ -101,7 +97,7 @@ function BinarySearchTree() {
|
|||||||
}
|
}
|
||||||
// case 2: target has one child
|
// case 2: target has one child
|
||||||
else if (children == 1) {
|
else if (children == 1) {
|
||||||
var newChild = (target.left !== null) ? target.left : target.right;
|
var newChild = target.left !== null ? target.left : target.right;
|
||||||
if (parent === null) {
|
if (parent === null) {
|
||||||
target.value = newChild.value;
|
target.value = newChild.value;
|
||||||
target.left = null;
|
target.left = null;
|
||||||
@ -120,90 +116,88 @@ function BinarySearchTree() {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
function searchTree(node) {
|
||||||
if (value < node.value) {
|
if (value < node.value) {
|
||||||
if (node.left == null) {
|
if (node.left == null) {
|
||||||
node.left = new Node(value);
|
node.left = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else if (node.left != null) {
|
} else if (node.left != null) {
|
||||||
return searchTree(node.left)
|
return searchTree(node.left);
|
||||||
};
|
}
|
||||||
} else if (value > node.value) {
|
} else if (value > node.value) {
|
||||||
if (node.right == null) {
|
if (node.right == null) {
|
||||||
node.right = new Node(value);
|
node.right = new Node(value);
|
||||||
return;
|
return;
|
||||||
} else if (node.right != null) {
|
} else if (node.right != null) {
|
||||||
return searchTree(node.right);
|
return searchTree(node.right);
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
inorder: function() {
|
|
||||||
if (this.root == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
var result = new Array();
|
|
||||||
function traverseInOrder(node) {
|
|
||||||
if (node.left != null) {
|
|
||||||
traverseInOrder(node.left);
|
|
||||||
};
|
|
||||||
result.push(node.value);
|
|
||||||
if (node.right != null) {
|
|
||||||
traverseInOrder(node.right);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
traverseInOrder(this.root);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
isBinarySearchTree() {
|
|
||||||
if (this.root == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
} else {
|
||||||
var check = true;
|
return null;
|
||||||
function checkTree(node) {
|
|
||||||
if (node.left != null) {
|
|
||||||
var left = node.left;
|
|
||||||
if (left.value > node.value) {
|
|
||||||
check = false;
|
|
||||||
} else {
|
|
||||||
checkTree(left);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node.right != null) {
|
|
||||||
var right = node.right;
|
|
||||||
if (right.value < node.value) {
|
|
||||||
check = false;
|
|
||||||
} else {
|
|
||||||
checkTree(right);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
checkTree(this.root);
|
|
||||||
return check;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return searchTree(node);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
inorder: function() {
|
||||||
|
if (this.root == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
var result = new Array();
|
||||||
|
function traverseInOrder(node) {
|
||||||
|
if (node.left != null) {
|
||||||
|
traverseInOrder(node.left);
|
||||||
|
}
|
||||||
|
result.push(node.value);
|
||||||
|
if (node.right != null) {
|
||||||
|
traverseInOrder(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traverseInOrder(this.root);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isBinarySearchTree() {
|
||||||
|
if (this.root == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
var check = true;
|
||||||
|
function checkTree(node) {
|
||||||
|
if (node.left != null) {
|
||||||
|
var left = node.left;
|
||||||
|
if (left.value > node.value) {
|
||||||
|
check = false;
|
||||||
|
} else {
|
||||||
|
checkTree(left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.right != null) {
|
||||||
|
var right = node.right;
|
||||||
|
if (right.value < node.value) {
|
||||||
|
check = false;
|
||||||
|
} else {
|
||||||
|
checkTree(right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkTree(this.root);
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -212,4 +206,5 @@ BinarySearchTree.prototype = {
|
|||||||
```js
|
```js
|
||||||
// solution required
|
// solution required
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -8,13 +8,12 @@ challengeType: 1
|
|||||||
<section id='description'>
|
<section id='description'>
|
||||||
In the last challenge we described a scenario in which a tree could become unbalanced. To understand the concept of balance, let's take a look at another tree property: height. Height in a tree represents the distance from the root node to any given leaf node. Different paths in a highly branched tree structure may have different heights, but for a given tree there will be a minimum and maximum height. If the tree is balanced, these values will differ at most by one. This means that in a balanced tree, all the leaf nodes exist within the same level, or if they are not within the same level they are at most one level apart.
|
In the last challenge we described a scenario in which a tree could become unbalanced. To understand the concept of balance, let's take a look at another tree property: height. Height in a tree represents the distance from the root node to any given leaf node. Different paths in a highly branched tree structure may have different heights, but for a given tree there will be a minimum and maximum height. If the tree is balanced, these values will differ at most by one. This means that in a balanced tree, all the leaf nodes exist within the same level, or if they are not within the same level they are at most one level apart.
|
||||||
The property of balance is important for trees because it is what determines the efficiency of tree operations. As we explained in the last challenge, we face worst case time complexity for heavily unbalanced trees. Self-balancing trees are commonly used to account for this issue in trees with dynamic data sets. Common examples of these include AVL trees, red-black trees, and B-trees. These trees all contain additional internal logic which re-balance the tree when insertions or deletions create a state of imbalance.
|
The property of balance is important for trees because it is what determines the efficiency of tree operations. As we explained in the last challenge, we face worst case time complexity for heavily unbalanced trees. Self-balancing trees are commonly used to account for this issue in trees with dynamic data sets. Common examples of these include AVL trees, red-black trees, and B-trees. These trees all contain additional internal logic which re-balance the tree when insertions or deletions create a state of imbalance.
|
||||||
Note: A similar property to height is depth, which refers to how far a given node is from the root node.
|
<strong>Note:</strong> A similar property to height is depth, which refers to how far a given node is from the root node.
|
||||||
Instructions: Write two methods for our binary tree: <code>findMinHeight</code> and <code>findMaxHeight</code>. These methods should return an integer value for the minimum and maximum height within a given binary tree, respectively. If the node is empty let's assign it a height of <code>-1</code> (that's the base case). Finally, add a third method <code>isBalanced</code> which returns <code>true</code> or <code>false</code> depending on whether the tree is balanced or not. You can use the first two methods you just wrote to determine this.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Write two methods for our binary tree: <code>findMinHeight</code> and <code>findMaxHeight</code>. These methods should return an integer value for the minimum and maximum height within a given binary tree, respectively. If the node is empty let's assign it a height of <code>-1</code> (that's the base case). Finally, add a third method <code>isBalanced</code> which returns <code>true</code> or <code>false</code> depending on whether the tree is balanced or not. You can use the first two methods you just wrote to determine this.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -38,150 +37,146 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMaxHeight !== 'function') { return false; }; return (test.findMaxHeight() == -1); })(), 'An empty tree returns a height of <code>-1</code>.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMaxHeight !== 'function') { return false; }; return (test.findMaxHeight() == -1); })(), 'An empty tree returns a height of <code>-1</code>.');
|
||||||
- text: The <code>isBalanced</code> method returns true if the tree is a balanced binary search tree.
|
- text: The <code>isBalanced</code> method returns true if the tree is a balanced binary search tree.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.isBalanced !== 'function') { return false; }; test.add(4); test.add(1); test.add(7); test.add(87); test.add(34); test.add(45); test.add(73); test.add(8); return !test.isBalanced(); })(), 'The <code>isBalanced</code> method returns true if the tree is a balanced binary search tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.isBalanced !== 'function') { return false; }; test.add(4); test.add(1); test.add(7); test.add(87); test.add(34); test.add(45); test.add(73); test.add(8); return !test.isBalanced(); })(), 'The <code>isBalanced</code> method returns true if the tree is a balanced binary search tree.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// change code below this line
|
// change code below this line
|
||||||
// change code above this line
|
// change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
function searchTree(node) {
|
||||||
|
if (value < node.value) {
|
||||||
|
if (node.left == null) {
|
||||||
|
node.left = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.left != null) {
|
||||||
|
return searchTree(node.left);
|
||||||
|
}
|
||||||
|
} else if (value > node.value) {
|
||||||
|
if (node.right == null) {
|
||||||
|
node.right = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.right != null) {
|
||||||
|
return searchTree(node.right);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
return null;
|
||||||
if (value < node.value) {
|
}
|
||||||
if (node.left == null) {
|
}
|
||||||
node.left = new Node(value);
|
return searchTree(node);
|
||||||
return;
|
|
||||||
} else if (node.left != null) {
|
|
||||||
return searchTree(node.left)
|
|
||||||
};
|
|
||||||
} else if (value > node.value) {
|
|
||||||
if (node.right == null) {
|
|
||||||
node.right = new Node(value);
|
|
||||||
return;
|
|
||||||
} else if (node.right != null) {
|
|
||||||
return searchTree(node.right);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// change code below this line
|
// change code below this line
|
||||||
// change code above this line
|
// change code above this line
|
||||||
this.findMinHeight = function(root = this.root) {
|
this.findMinHeight = function(root = this.root) {
|
||||||
// empty tree.
|
// empty tree.
|
||||||
if(root === null) {
|
if (root === null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// leaf node.
|
// leaf node.
|
||||||
if(root.left === null && root.right === null) {
|
if (root.left === null && root.right === null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(root.left === null){
|
if (root.left === null) {
|
||||||
return this.findMinHeight(root.right) + 1;
|
return this.findMinHeight(root.right) + 1;
|
||||||
}
|
}
|
||||||
if(root.right === null){
|
if (root.right === null) {
|
||||||
return this.findMinHeight(root.left) + 1;
|
return this.findMinHeight(root.left) + 1;
|
||||||
}
|
}
|
||||||
const lHeight = this.findMinHeight(root.left);
|
const lHeight = this.findMinHeight(root.left);
|
||||||
const rHeight = this.findMinHeight(root.right);
|
const rHeight = this.findMinHeight(root.right);
|
||||||
return Math.min(lHeight, rHeight) + 1;
|
return Math.min(lHeight, rHeight) + 1;
|
||||||
};
|
};
|
||||||
this.findMaxHeight = function(root = this.root) {
|
this.findMaxHeight = function(root = this.root) {
|
||||||
// empty tree.
|
// empty tree.
|
||||||
if(root === null) {
|
if (root === null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// leaf node.
|
// leaf node.
|
||||||
if(root.left === null && root.right === null) {
|
if (root.left === null && root.right === null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(root.left === null){
|
if (root.left === null) {
|
||||||
return this.findMaxHeight(root.right) + 1;
|
return this.findMaxHeight(root.right) + 1;
|
||||||
}
|
}
|
||||||
if(root.right === null){
|
if (root.right === null) {
|
||||||
return this.findMaxHeight(root.left) + 1;
|
return this.findMaxHeight(root.left) + 1;
|
||||||
}
|
}
|
||||||
const lHeight = this.findMaxHeight(root.left);
|
const lHeight = this.findMaxHeight(root.left);
|
||||||
const rHeight = this.findMaxHeight(root.right);
|
const rHeight = this.findMaxHeight(root.right);
|
||||||
return Math.max(lHeight, rHeight) + 1;
|
return Math.max(lHeight, rHeight) + 1;
|
||||||
};
|
};
|
||||||
this.isBalanced = function(root = this.root) {
|
this.isBalanced = function(root = this.root) {
|
||||||
|
if (root === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(root === null) {
|
if (root.left === null && root.right === null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(root.left === null && root.right === null){
|
if (root.left === null) {
|
||||||
return true;
|
return this.findMaxHeight(root.right) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(root.left === null) {
|
if (root.right === null) {
|
||||||
return this.findMaxHeight(root.right) <= 0;
|
return this.findMaxHeight(root.left) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(root.right === null) {
|
const lHeight = this.findMaxHeight(root.left);
|
||||||
return this.findMaxHeight(root.left) <= 0;
|
const rHeight = this.findMaxHeight(root.right);
|
||||||
}
|
if (Math.abs(lHeight - rHeight) > 1) {
|
||||||
|
return false;
|
||||||
const lHeight = this.findMaxHeight(root.left);
|
}
|
||||||
const rHeight = this.findMaxHeight(root.right);
|
return this.isBalanced(root.left) && this.isBalanced(root.right);
|
||||||
if(Math.abs(lHeight - rHeight) > 1){
|
};
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.isBalanced(root.left) && this.isBalanced(root.right);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -12,12 +12,11 @@ To begin, we will discuss a particular type of a tree, the binary tree. In fact,
|
|||||||
<div style='width: 100%; display: flex; justify-content: center; align-items: center;'><img style='width: 100%; max-width: 350px;' src='https://user-images.githubusercontent.com/18563015/32136009-1e665d98-bbd6-11e7-9133-63184f9f9182.png'></div>
|
<div style='width: 100%; display: flex; justify-content: center; align-items: center;'><img style='width: 100%; max-width: 350px;' src='https://user-images.githubusercontent.com/18563015/32136009-1e665d98-bbd6-11e7-9133-63184f9f9182.png'></div>
|
||||||
Now this ordered relationship is very easy to see. Note that every value to the left of 8, the root node, is less than 8, and every value to the right is greater than 8. Also notice that this relationship applies to each of the subtrees as well. For example, the first left child is a subtree. 3 is the parent node, and it has exactly two child nodes — by the rules governing binary search trees, we know without even looking that the left child of this node (and any of its children) will be less than 3, and the right child (and any of its children) will be greater than 3 (but also less than the structure's root value), and so on.
|
Now this ordered relationship is very easy to see. Note that every value to the left of 8, the root node, is less than 8, and every value to the right is greater than 8. Also notice that this relationship applies to each of the subtrees as well. For example, the first left child is a subtree. 3 is the parent node, and it has exactly two child nodes — by the rules governing binary search trees, we know without even looking that the left child of this node (and any of its children) will be less than 3, and the right child (and any of its children) will be greater than 3 (but also less than the structure's root value), and so on.
|
||||||
Binary search trees are very common and useful data structures because they provide logarithmic time in the average case for several common operations such as lookup, insertion, and deletion.
|
Binary search trees are very common and useful data structures because they provide logarithmic time in the average case for several common operations such as lookup, insertion, and deletion.
|
||||||
Instructions: We'll start simple. We've defined the skeleton of a binary search tree structure here in addition to a function to create nodes for our tree. Observe that each node may have a left and right value. These will be assigned child subtrees if they exist. In our binary search tree, define two methods, <code>findMin</code> and <code>findMax</code>. These methods should return the minimum and maximum value held in the binary search tree (don't worry about adding values to the tree for now, we have added some in the background). If you get stuck, reflect on the invariant that must be true for binary search trees: each left subtree is less than or equal to its parent and each right subtree is greater than or equal to its parent. Let's also say that our tree can only store integer values. If the tree is empty, either method should return <code>null</code>.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
We'll start simple. We've defined the skeleton of a binary search tree structure here in addition to a function to create nodes for our tree. Observe that each node may have a left and right value. These will be assigned child subtrees if they exist. In our binary search tree, define two methods, <code>findMin</code> and <code>findMax</code>. These methods should return the minimum and maximum value held in the binary search tree (don't worry about adding values to the tree for now, we have added some in the background). If you get stuck, reflect on the invariant that must be true for binary search trees: each left subtree is less than or equal to its parent and each right subtree is greater than or equal to its parent. Let's also say that our tree can only store integer values. If the tree is empty, either method should return <code>null</code>.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -37,7 +36,6 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMax !== 'function') { return false; }; test.add(4); test.add(1); test.add(7); test.add(87); test.add(34); test.add(45); test.add(73); test.add(8); return test.findMax() == 87; })(), 'The <code>findMax</code> method returns the maximum value in the binary search tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMax !== 'function') { return false; }; test.add(4); test.add(1); test.add(7); test.add(87); test.add(34); test.add(45); test.add(73); test.add(8); return test.findMax() == 87; })(), 'The <code>findMax</code> method returns the maximum value in the binary search tree.');
|
||||||
- text: The <code>findMin</code> and <code>findMax</code> methods return <code>null</code> for an empty tree.
|
- text: The <code>findMin</code> and <code>findMax</code> methods return <code>null</code> for an empty tree.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMin !== 'function') { return false; }; if (typeof test.findMax !== 'function') { return false; }; return (test.findMin() == null && test.findMax() == null) })(), 'The <code>findMin</code> and <code>findMax</code> methods return <code>null</code> for an empty tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMin !== 'function') { return false; }; if (typeof test.findMax !== 'function') { return false; }; return (test.findMin() == null && test.findMax() == null) })(), 'The <code>findMin</code> and <code>findMax</code> methods return <code>null</code> for an empty tree.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@ -48,60 +46,58 @@ tests:
|
|||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// change code below this line
|
// change code below this line
|
||||||
// change code above this line
|
// change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
function searchTree(node) {
|
||||||
|
if (value < node.value) {
|
||||||
|
if (node.left == null) {
|
||||||
|
node.left = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.left != null) {
|
||||||
|
return searchTree(node.left);
|
||||||
|
}
|
||||||
|
} else if (value > node.value) {
|
||||||
|
if (node.right == null) {
|
||||||
|
node.right = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.right != null) {
|
||||||
|
return searchTree(node.right);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
return null;
|
||||||
if (value < node.value) {
|
}
|
||||||
if (node.left == null) {
|
}
|
||||||
node.left = new Node(value);
|
return searchTree(node);
|
||||||
return;
|
|
||||||
} else if (node.left != null) {
|
|
||||||
return searchTree(node.left)
|
|
||||||
};
|
|
||||||
} else if (value > node.value) {
|
|
||||||
if (node.right == null) {
|
|
||||||
node.right = new Node(value);
|
|
||||||
return;
|
|
||||||
} else if (node.right != null) {
|
|
||||||
return searchTree(node.right);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -111,173 +107,174 @@ BinarySearchTree.prototype = {
|
|||||||
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
|
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
this.findMin = function() {
|
this.findMin = function() {
|
||||||
// Empty tree.
|
// Empty tree.
|
||||||
if (!this.root) {
|
if (!this.root) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let currentNode = this.root;
|
let currentNode = this.root;
|
||||||
while (currentNode.left) {
|
while (currentNode.left) {
|
||||||
currentNode = currentNode.left;
|
currentNode = currentNode.left;
|
||||||
}
|
}
|
||||||
return currentNode.value;
|
return currentNode.value;
|
||||||
};
|
};
|
||||||
this.findMax = function() {
|
this.findMax = function() {
|
||||||
// Empty tree.
|
// Empty tree.
|
||||||
if (!this.root) {
|
if (!this.root) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let currentNode = this.root;
|
let currentNode = this.root;
|
||||||
while (currentNode.right) {
|
while (currentNode.right) {
|
||||||
currentNode = currentNode.right;
|
currentNode = currentNode.right;
|
||||||
}
|
}
|
||||||
return currentNode.value;
|
return currentNode.value;
|
||||||
};
|
};
|
||||||
this.add = function(value) {
|
this.add = function(value) {
|
||||||
// Empty tree.
|
// Empty tree.
|
||||||
if (!this.root) {
|
if (!this.root) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return this.addNode(this.root, value);
|
return this.addNode(this.root, value);
|
||||||
};
|
};
|
||||||
this.addNode = function(node, value) {
|
this.addNode = function(node, value) {
|
||||||
// Check if value already exists.
|
// Check if value already exists.
|
||||||
if (node.value === value) return null;
|
if (node.value === value) return null;
|
||||||
if (value < node.value) {
|
if (value < node.value) {
|
||||||
if (node.left) {
|
if (node.left) {
|
||||||
return this.addNode(node.left, value);
|
return this.addNode(node.left, value);
|
||||||
} else {
|
} else {
|
||||||
node.left = new Node(value);
|
node.left = new Node(value);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (node.right) {
|
if (node.right) {
|
||||||
return this.addNode(node.right, value);
|
return this.addNode(node.right, value);
|
||||||
} else {
|
} else {
|
||||||
node.right = new Node(value);
|
node.right = new Node(value);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.isPresent = function(value) {
|
this.isPresent = function(value) {
|
||||||
if (!this.root) {
|
if (!this.root) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.isNodePresent(this.root, value);
|
return this.isNodePresent(this.root, value);
|
||||||
};
|
};
|
||||||
this.isNodePresent = function(node, value) {
|
this.isNodePresent = function(node, value) {
|
||||||
if (node.value === value) return true;
|
if (node.value === value) return true;
|
||||||
if (value < node.value) {
|
if (value < node.value) {
|
||||||
return node.left ? this.isNodePresent(node.left, value) : false;
|
return node.left ? this.isNodePresent(node.left, value) : false;
|
||||||
} else {
|
} else {
|
||||||
return node.right ? this.isNodePresent(node.right, value) : false;
|
return node.right ? this.isNodePresent(node.right, value) : false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
this.findMinHeight = function() {
|
this.findMinHeight = function() {
|
||||||
if (!this.root) {
|
if (!this.root) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
let heights = {};
|
let heights = {};
|
||||||
let height = 0;
|
let height = 0;
|
||||||
this.traverseTree(this.root, height, heights);
|
this.traverseTree(this.root, height, heights);
|
||||||
return Math.min(...Object.keys(heights));
|
return Math.min(...Object.keys(heights));
|
||||||
};
|
};
|
||||||
this.findMaxHeight = function() {
|
this.findMaxHeight = function() {
|
||||||
if (!this.root) {
|
if (!this.root) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
let heights = {};
|
let heights = {};
|
||||||
let height = 0;
|
let height = 0;
|
||||||
this.traverseTree(this.root, height, heights);
|
this.traverseTree(this.root, height, heights);
|
||||||
return Math.max(...Object.keys(heights));
|
return Math.max(...Object.keys(heights));
|
||||||
};
|
};
|
||||||
this.traverseTree = function(node, height, heights) {
|
this.traverseTree = function(node, height, heights) {
|
||||||
if (node.left === null && node.right === null) {
|
if (node.left === null && node.right === null) {
|
||||||
return (heights[height] = true);
|
return (heights[height] = true);
|
||||||
}
|
}
|
||||||
if (node.left) {
|
if (node.left) {
|
||||||
this.traverseTree(node.left, height + 1, heights);
|
this.traverseTree(node.left, height + 1, heights);
|
||||||
}
|
}
|
||||||
if (node.right) {
|
if (node.right) {
|
||||||
this.traverseTree(node.right, height + 1, heights);
|
this.traverseTree(node.right, height + 1, heights);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.isBalanced = function() {
|
this.isBalanced = function() {
|
||||||
return this.findMaxHeight() > this.findMinHeight() + 1;
|
return this.findMaxHeight() > this.findMinHeight() + 1;
|
||||||
};
|
};
|
||||||
// DFS tree traversal.
|
// DFS tree traversal.
|
||||||
this.inorder = function() {
|
this.inorder = function() {
|
||||||
if (!this.root) return null;
|
if (!this.root) return null;
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
function traverseInOrder(node) {
|
function traverseInOrder(node) {
|
||||||
if (node.left) traverseInOrder(node.left);
|
if (node.left) traverseInOrder(node.left);
|
||||||
result.push(node.value);
|
result.push(node.value);
|
||||||
if (node.right) traverseInOrder(node.right);
|
if (node.right) traverseInOrder(node.right);
|
||||||
}
|
}
|
||||||
traverseInOrder(this.root);
|
traverseInOrder(this.root);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
this.preorder = function() {
|
this.preorder = function() {
|
||||||
if (!this.root) return null;
|
if (!this.root) return null;
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
function traverseInOrder(node) {
|
function traverseInOrder(node) {
|
||||||
result.push(node.value);
|
result.push(node.value);
|
||||||
if (node.left) traverseInOrder(node.left);
|
if (node.left) traverseInOrder(node.left);
|
||||||
if (node.right) traverseInOrder(node.right);
|
if (node.right) traverseInOrder(node.right);
|
||||||
}
|
}
|
||||||
traverseInOrder(this.root);
|
traverseInOrder(this.root);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
this.postorder = function() {
|
this.postorder = function() {
|
||||||
if (!this.root) return null;
|
if (!this.root) return null;
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
function traverseInOrder(node) {
|
function traverseInOrder(node) {
|
||||||
if (node.left) traverseInOrder(node.left);
|
if (node.left) traverseInOrder(node.left);
|
||||||
if (node.right) traverseInOrder(node.right);
|
if (node.right) traverseInOrder(node.right);
|
||||||
result.push(node.value);
|
result.push(node.value);
|
||||||
}
|
}
|
||||||
traverseInOrder(this.root);
|
traverseInOrder(this.root);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
// BFS tree traversal.
|
// BFS tree traversal.
|
||||||
this.levelOrder = function() {
|
this.levelOrder = function() {
|
||||||
if (!this.root) return null;
|
if (!this.root) return null;
|
||||||
let queue = [this.root];
|
let queue = [this.root];
|
||||||
let result = [];
|
let result = [];
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
let node = queue.shift();
|
let node = queue.shift();
|
||||||
result.push(node.value);
|
result.push(node.value);
|
||||||
if (node.left) queue.push(node.left);
|
if (node.left) queue.push(node.left);
|
||||||
if (node.right) queue.push(node.right);
|
if (node.right) queue.push(node.right);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
this.reverseLevelOrder = function() {
|
this.reverseLevelOrder = function() {
|
||||||
if (!this.root) return null;
|
if (!this.root) return null;
|
||||||
let queue = [this.root];
|
let queue = [this.root];
|
||||||
let result = [];
|
let result = [];
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
let node = queue.shift();
|
let node = queue.shift();
|
||||||
result.push(node.value);
|
result.push(node.value);
|
||||||
if (node.right) queue.push(node.right);
|
if (node.right) queue.push(node.right);
|
||||||
if (node.left) queue.push(node.left);
|
if (node.left) queue.push(node.left);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
// Delete a leaf node.
|
// Delete a leaf node.
|
||||||
}
|
}
|
||||||
let bst = new BinarySearchTree();
|
let bst = new BinarySearchTree();
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -8,12 +8,11 @@ challengeType: 1
|
|||||||
<section id='description'>
|
<section id='description'>
|
||||||
Now that we can add and remove elements let's see some of the applications heaps can be used for. Heaps are commonly used to implement priority queues because they always store an item of greatest or least value in first position. In addition, they are used to implement a sorting algorithm called heap sort. We'll see how to do this here. Heap sort uses a min heap, the reverse of a max heap. A min heap always stores the element of least value in the root position.
|
Now that we can add and remove elements let's see some of the applications heaps can be used for. Heaps are commonly used to implement priority queues because they always store an item of greatest or least value in first position. In addition, they are used to implement a sorting algorithm called heap sort. We'll see how to do this here. Heap sort uses a min heap, the reverse of a max heap. A min heap always stores the element of least value in the root position.
|
||||||
Heap sort works by taking an unsorted array, adding each item in the array into a min heap, and then extracting every item out of the min heap into a new array. The min heap structure ensures that the new array will contain the original items in least to greatest order. This is one of the most efficient sorting algorithms with average and worst case performance of O(nlog(n)).
|
Heap sort works by taking an unsorted array, adding each item in the array into a min heap, and then extracting every item out of the min heap into a new array. The min heap structure ensures that the new array will contain the original items in least to greatest order. This is one of the most efficient sorting algorithms with average and worst case performance of O(nlog(n)).
|
||||||
Instructions: Let's implement heap sort with a min heap. Feel free to adapt your max heap code here. Create an object MinHeap with insert, remove, and sort methods. The sort method should return an array of all the elements in the min heap sorted from smallest to largest.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Let's implement heap sort with a min heap. Feel free to adapt your max heap code here. Create an object <code>MinHeap</code> with <code>insert</code>, <code>remove</code>, and <code>sort</code> methods. The <code>sort</code> method should return an array of all the elements in the min heap sorted from smallest to largest.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -31,7 +30,6 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() } else { return false; }; return (typeof test.sort == 'function')})(), 'MinHeap has a method called sort.');
|
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() } else { return false; }; return (typeof test.sort == 'function')})(), 'MinHeap has a method called sort.');
|
||||||
- text: The sort method returns an array containing all items added to the min heap in sorted order.
|
- text: The sort method returns an array containing all items added to the min heap in sorted order.
|
||||||
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() } else { return false; }; test.insert(3); test.insert(12); test.insert(5); test.insert(10); test.insert(1); test.insert(27); test.insert(42); test.insert(57); test.insert(5); var result = test.sort(); return (isSorted(result)); })(), 'The sort method returns an array containing all items added to the min heap in sorted order.');
|
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() } else { return false; }; test.insert(3); test.insert(12); test.insert(5); test.insert(10); test.insert(1); test.insert(27); test.insert(42); test.insert(57); test.insert(5); var result = test.sort(); return (isSorted(result)); })(), 'The sort method returns an array containing all items added to the min heap in sorted order.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@ -44,14 +42,15 @@ tests:
|
|||||||
```js
|
```js
|
||||||
// check if array is sorted
|
// check if array is sorted
|
||||||
function isSorted(arr) {
|
function isSorted(arr) {
|
||||||
var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);
|
var check = i =>
|
||||||
|
i == arr.length - 1 ? true : arr[i] > arr[i + 1] ? false : check(i + 1);
|
||||||
return check(0);
|
return check(0);
|
||||||
}
|
}
|
||||||
// generate a randomly filled array
|
// generate a randomly filled array
|
||||||
var array = new Array();
|
var array = new Array();
|
||||||
(function createArray(size = 5) {
|
(function createArray(size = 5) {
|
||||||
array.push(+(Math.random() * 100).toFixed(0));
|
array.push(+(Math.random() * 100).toFixed(0));
|
||||||
return (size > 1) ? createArray(size - 1) : undefined;
|
return size > 1 ? createArray(size - 1) : undefined;
|
||||||
})(25);
|
})(25);
|
||||||
var MinHeap = function() {
|
var MinHeap = function() {
|
||||||
// change code below this line
|
// change code below this line
|
||||||
@ -60,9 +59,6 @@ var MinHeap = function() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -66,7 +66,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -48,7 +48,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -59,9 +58,6 @@ var MaxHeap = function() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -34,7 +34,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -109,7 +108,6 @@ BinarySearchTree.prototype = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -39,7 +39,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -50,8 +49,6 @@ var homeworkStack = ["BIO12","HIS80","MAT122","PSY44"];
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -97,15 +97,11 @@ function Set() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function Set() {
|
function Set() {
|
||||||
// the var collection will hold the set
|
// the var collection will hold the set
|
||||||
|
@ -39,7 +39,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -116,15 +115,11 @@ function Set() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function Set() {var collection = []; this.has = function(e){return(collection.indexOf(e) !== -1);};this.values = function() {return collection;};this.add = function(element) {if (!this.has(element)) {collection.push(element);return true;} else {return false;}};this.remove = function(element) {if(this.has(element)) {var i = collection.indexOf(element);collection.splice(i, 1);return true;}return false;};this.size = function() {return collection.length;};this.union = function(set) {var u = new Set();var c = this.values();var s = set.values();c.forEach(function(element){u.add(element);});s.forEach(function(element){u.add(element);});return u;};this.intersection = function(set) {var i = new Set();var c = this.values();c.forEach(function(element){if(s.has(element)) i.add(element);});};this.difference = function(set) {var d = new Set();var c = this.values();c.forEach(function(e){if(!set.has(e)) d.add(e);});};this.subset = function(set) {var isSubset = true;var c = this.values();c.forEach(function(e){if(!set.has(e)) isSubset = false;});return isSubset;};}
|
function Set() {var collection = []; this.has = function(e){return(collection.indexOf(e) !== -1);};this.values = function() {return collection;};this.add = function(element) {if (!this.has(element)) {collection.push(element);return true;} else {return false;}};this.remove = function(element) {if(this.has(element)) {var i = collection.indexOf(element);collection.splice(i, 1);return true;}return false;};this.size = function() {return collection.length;};this.union = function(set) {var u = new Set();var c = this.values();var s = set.values();c.forEach(function(element){u.add(element);});s.forEach(function(element){u.add(element);});return u;};this.intersection = function(set) {var i = new Set();var c = this.values();c.forEach(function(element){if(s.has(element)) i.add(element);});};this.difference = function(set) {var d = new Set();var c = this.values();c.forEach(function(e){if(!set.has(e)) d.add(e);});};this.subset = function(set) {var isSubset = true;var c = this.values();c.forEach(function(e){if(!set.has(e)) isSubset = false;});return isSubset;};}
|
||||||
```
|
```
|
||||||
|
@ -30,7 +30,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -73,15 +72,11 @@ function Set() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function Set() {
|
function Set() {
|
||||||
var collection = [];
|
var collection = [];
|
||||||
|
@ -31,7 +31,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -86,9 +85,6 @@ function Set() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -40,7 +40,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -51,9 +50,6 @@ var MaxHeap = function() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -41,7 +41,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -86,9 +85,6 @@ function LinkedList() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -40,7 +40,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -38,7 +38,6 @@ tests:
|
|||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
<section id='challengeSeed'>
|
<section id='challengeSeed'>
|
||||||
|
|
||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -52,15 +51,11 @@ function checkSet(){
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function checkSet(){
|
function checkSet(){
|
||||||
var set = new Set([1,2,3,4,5]);
|
var set = new Set([1,2,3,4,5]);
|
||||||
|
@ -101,8 +101,6 @@ function LinkedList() {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -76,14 +76,11 @@ var i32View;
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var buffer = new ArrayBuffer(64);
|
var buffer = new ArrayBuffer(64);
|
||||||
var i32View = new Int32Array(buffer);
|
var i32View = new Int32Array(buffer);
|
||||||
|
@ -50,14 +50,11 @@ checkSet([ 1, 2, 3], 2); // Should return [ true, 3 ]
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function checkSet(arrToBeSet, checkValue){
|
function checkSet(arrToBeSet, checkValue){
|
||||||
var set = new Set(arrToBeSet);
|
var set = new Set(arrToBeSet);
|
||||||
|
@ -8,12 +8,11 @@ challengeType: 1
|
|||||||
<section id='description'>
|
<section id='description'>
|
||||||
Here we will introduce another tree traversal method: breadth-first search. In contrast to the depth-first search methods from the last challenge, breadth-first search explores all the nodes in a given level within a tree before continuing on to the next level. Typically, queues are utilized as helper data structures in the design of breadth-first search algorithms.
|
Here we will introduce another tree traversal method: breadth-first search. In contrast to the depth-first search methods from the last challenge, breadth-first search explores all the nodes in a given level within a tree before continuing on to the next level. Typically, queues are utilized as helper data structures in the design of breadth-first search algorithms.
|
||||||
In this method, we start by adding the root node to a queue. Then we begin a loop where we dequeue the first item in the queue, add it to a new array, and then inspect both its child subtrees. If its children are not null, they are each enqueued. This process continues until the queue is empty.
|
In this method, we start by adding the root node to a queue. Then we begin a loop where we dequeue the first item in the queue, add it to a new array, and then inspect both its child subtrees. If its children are not null, they are each enqueued. This process continues until the queue is empty.
|
||||||
Instructions: Let's create a breadth-first search method in our tree called <code>levelOrder</code>. This method should return an array containing the values of all the tree nodes, explored in a breadth-first manner. Be sure to return the values in the array, not the nodes themselves. A level should be traversed from left to right. Next, let's write a similar method called <code>reverseLevelOrder</code> which performs the same search but in the reverse direction (right to left) at each level.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Let's create a breadth-first search method in our tree called <code>levelOrder</code>. This method should return an array containing the values of all the tree nodes, explored in a breadth-first manner. Be sure to return the values in the array, not the nodes themselves. A level should be traversed from left to right. Next, let's write a similar method called <code>reverseLevelOrder</code> which performs the same search but in the reverse direction (right to left) at each level.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -35,7 +34,6 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.levelOrder !== 'function') { return false; }; return (test.levelOrder() == null); })(), 'The <code>levelOrder</code> method returns <code>null</code> for an empty tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.levelOrder !== 'function') { return false; }; return (test.levelOrder() == null); })(), 'The <code>levelOrder</code> method returns <code>null</code> for an empty tree.');
|
||||||
- text: The <code>reverseLevelOrder</code> method returns <code>null</code> for an empty tree.
|
- text: The <code>reverseLevelOrder</code> method returns <code>null</code> for an empty tree.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.reverseLevelOrder !== 'function') { return false; }; return (test.reverseLevelOrder() == null); })(), 'The <code>reverseLevelOrder</code> method returns <code>null</code> for an empty tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.reverseLevelOrder !== 'function') { return false; }; return (test.reverseLevelOrder() == null); })(), 'The <code>reverseLevelOrder</code> method returns <code>null</code> for an empty tree.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@ -46,60 +44,58 @@ tests:
|
|||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// change code below this line
|
// change code below this line
|
||||||
// change code above this line
|
// change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
function searchTree(node) {
|
||||||
|
if (value < node.value) {
|
||||||
|
if (node.left == null) {
|
||||||
|
node.left = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.left != null) {
|
||||||
|
return searchTree(node.left);
|
||||||
|
}
|
||||||
|
} else if (value > node.value) {
|
||||||
|
if (node.right == null) {
|
||||||
|
node.right = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.right != null) {
|
||||||
|
return searchTree(node.right);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
return null;
|
||||||
if (value < node.value) {
|
}
|
||||||
if (node.left == null) {
|
}
|
||||||
node.left = new Node(value);
|
return searchTree(node);
|
||||||
return;
|
|
||||||
} else if (node.left != null) {
|
|
||||||
return searchTree(node.left)
|
|
||||||
};
|
|
||||||
} else if (value > node.value) {
|
|
||||||
if (node.right == null) {
|
|
||||||
node.right = new Node(value);
|
|
||||||
return;
|
|
||||||
} else if (node.right != null) {
|
|
||||||
return searchTree(node.right);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -108,4 +104,5 @@ BinarySearchTree.prototype = {
|
|||||||
```js
|
```js
|
||||||
// solution required
|
// solution required
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -11,13 +11,12 @@ In-order: Begin the search at the left-most node and end at the right-most node.
|
|||||||
Pre-order: Explore all the roots before the leaves.
|
Pre-order: Explore all the roots before the leaves.
|
||||||
Post-order: Explore all the leaves before the roots.
|
Post-order: Explore all the leaves before the roots.
|
||||||
As you may guess, you may choose different search methods depending on what type of data your tree is storing and what you are looking for. For a binary search tree, an inorder traversal returns the nodes in sorted order.
|
As you may guess, you may choose different search methods depending on what type of data your tree is storing and what you are looking for. For a binary search tree, an inorder traversal returns the nodes in sorted order.
|
||||||
Instructions: Here we will create these three search methods on our binary search tree. Depth-first search is an inherently recursive operation which continues to explore further subtrees so long as child nodes are present. Once you understand this basic concept, you can simply rearrange the order in which you explore the nodes and subtrees to produce any of the three searches above. For example, in post-order search we would want to recurse all the way to a leaf node before we begin to return any of the nodes themselves, whereas in pre-order search we would want to return the nodes first, and then continue recursing down the tree.
|
|
||||||
Define <code>inorder</code>, <code>preorder</code>, and <code>postorder</code> methods on our tree. Each of these methods should return an array of items which represent the tree traversal. Be sure to return the integer values at each node in the array, not the nodes themselves. Finally, return <code>null</code> if the tree is empty.
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
<section id='instructions'>
|
<section id='instructions'>
|
||||||
|
Here we will create these three search methods on our binary search tree. Depth-first search is an inherently recursive operation which continues to explore further subtrees so long as child nodes are present. Once you understand this basic concept, you can simply rearrange the order in which you explore the nodes and subtrees to produce any of the three searches above. For example, in post-order search we would want to recurse all the way to a leaf node before we begin to return any of the nodes themselves, whereas in pre-order search we would want to return the nodes first, and then continue recursing down the tree.
|
||||||
|
Define <code>inorder</code>, <code>preorder</code>, and <code>postorder</code> methods on our tree. Each of these methods should return an array of items which represent the tree traversal. Be sure to return the integer values at each node in the array, not the nodes themselves. Finally, return <code>null</code> if the tree is empty.
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -45,9 +44,7 @@ tests:
|
|||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.preorder !== 'function') { return false; }; return (test.preorder() == null); })(), 'The <code>preorder</code> method returns <code>null</code> for an empty tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.preorder !== 'function') { return false; }; return (test.preorder() == null); })(), 'The <code>preorder</code> method returns <code>null</code> for an empty tree.');
|
||||||
- text: The <code>postorder</code> method returns <code>null</code> for an empty tree.
|
- text: The <code>postorder</code> method returns <code>null</code> for an empty tree.
|
||||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.postorder !== 'function') { return false; }; return (test.postorder() == null); })(), 'The <code>postorder</code> method returns <code>null</code> for an empty tree.');
|
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.postorder !== 'function') { return false; }; return (test.postorder() == null); })(), 'The <code>postorder</code> method returns <code>null</code> for an empty tree.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Challenge Seed
|
## Challenge Seed
|
||||||
@ -56,105 +53,102 @@ tests:
|
|||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
// change code below this line
|
// change code below this line
|
||||||
// change code above this line
|
// change code above this line
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
### After Test
|
### After Test
|
||||||
<div id='js-teardown'>
|
<div id='js-teardown'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
BinarySearchTree.prototype = {
|
BinarySearchTree.prototype = {
|
||||||
add: function(value) {
|
add: function(value) {
|
||||||
var node = this.root;
|
var node = this.root;
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
this.root = new Node(value);
|
this.root = new Node(value);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
function searchTree(node) {
|
||||||
|
if (value < node.value) {
|
||||||
|
if (node.left == null) {
|
||||||
|
node.left = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.left != null) {
|
||||||
|
return searchTree(node.left);
|
||||||
|
}
|
||||||
|
} else if (value > node.value) {
|
||||||
|
if (node.right == null) {
|
||||||
|
node.right = new Node(value);
|
||||||
|
return;
|
||||||
|
} else if (node.right != null) {
|
||||||
|
return searchTree(node.right);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
function searchTree(node) {
|
return null;
|
||||||
if (value < node.value) {
|
}
|
||||||
if (node.left == null) {
|
}
|
||||||
node.left = new Node(value);
|
return searchTree(node);
|
||||||
return;
|
|
||||||
} else if (node.left != null) {
|
|
||||||
return searchTree(node.left)
|
|
||||||
};
|
|
||||||
} else if (value > node.value) {
|
|
||||||
if (node.right == null) {
|
|
||||||
node.right = new Node(value);
|
|
||||||
return;
|
|
||||||
} else if (node.right != null) {
|
|
||||||
return searchTree(node.right);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return searchTree(node);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
<section id='solution'>
|
<section id='solution'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
|
||||||
function Node(value) {
|
function Node(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.left = null;
|
this.left = null;
|
||||||
this.right = null;
|
this.right = null;
|
||||||
}
|
}
|
||||||
function BinarySearchTree() {
|
function BinarySearchTree() {
|
||||||
this.root = null;
|
this.root = null;
|
||||||
this.result = [];
|
this.result = [];
|
||||||
|
|
||||||
this.inorder = function(node) {
|
this.inorder = function(node) {
|
||||||
if (!node) node = this.root;
|
if (!node) node = this.root;
|
||||||
if (!node) return null;
|
if (!node) return null;
|
||||||
|
|
||||||
if (node.left) this.inorder(node.left);
|
if (node.left) this.inorder(node.left);
|
||||||
this.result.push(node.value)
|
this.result.push(node.value);
|
||||||
if (node.right) this.inorder(node.right);
|
if (node.right) this.inorder(node.right);
|
||||||
return this.result;
|
return this.result;
|
||||||
|
};
|
||||||
|
this.preorder = function(node) {
|
||||||
|
if (!node) node = this.root;
|
||||||
|
if (!node) return null;
|
||||||
|
|
||||||
};
|
this.result.push(node.value);
|
||||||
this.preorder = function(node) {
|
if (node.left) this.preorder(node.left);
|
||||||
if (!node) node = this.root;
|
if (node.right) this.preorder(node.right);
|
||||||
if (!node) return null;
|
return this.result;
|
||||||
|
};
|
||||||
|
this.postorder = function(node) {
|
||||||
|
if (!node) node = this.root;
|
||||||
|
if (!node) return null;
|
||||||
|
|
||||||
this.result.push(node.value);
|
if (node.left) this.postorder(node.left);
|
||||||
if (node.left) this.preorder(node.left);
|
if (node.right) this.postorder(node.right);
|
||||||
if (node.right) this.preorder(node.right);
|
this.result.push(node.value);
|
||||||
return this.result;
|
|
||||||
};
|
|
||||||
this.postorder = function(node) {
|
|
||||||
if (!node) node = this.root;
|
|
||||||
if (!node) return null;
|
|
||||||
|
|
||||||
if (node.left) this.postorder(node.left);
|
return this.result;
|
||||||
if (node.right) this.postorder(node.right);
|
};
|
||||||
this.result.push(node.value);
|
|
||||||
|
|
||||||
return this.result;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</section>
|
</section>
|
||||||
|
@ -51,8 +51,6 @@ function checkSet(set){
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
|
@ -25,7 +25,6 @@ tests:
|
|||||||
testString: assert(Puppy.next.element === "Cat", 'Your <code>Puppy</code> node should have a reference to a <code>Cat</code> node.');
|
testString: assert(Puppy.next.element === "Cat", 'Your <code>Puppy</code> node should have a reference to a <code>Cat</code> node.');
|
||||||
- text: Your <code>Cat</code> node should have a reference to a <code>Dog</code> node.
|
- text: Your <code>Cat</code> node should have a reference to a <code>Dog</code> node.
|
||||||
testString: assert(Cat.next.element === "Dog", 'Your <code>Cat</code> node should have a reference to a <code>Dog</code> node.');
|
testString: assert(Cat.next.element === "Dog", 'Your <code>Cat</code> node should have a reference to a <code>Dog</code> node.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@ -36,12 +35,12 @@ tests:
|
|||||||
<div id='js-seed'>
|
<div id='js-seed'>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var Node = function(element){
|
var Node = function(element) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.next = null;
|
this.next = null;
|
||||||
};
|
};
|
||||||
var Kitten = new Node("Kitten");
|
var Kitten = new Node('Kitten');
|
||||||
var Puppy = new Node("Puppy");
|
var Puppy = new Node('Puppy');
|
||||||
|
|
||||||
Kitten.next = Puppy;
|
Kitten.next = Puppy;
|
||||||
// only add code below this line
|
// only add code below this line
|
||||||
@ -51,9 +50,6 @@ console.log(Kitten.next);
|
|||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
## Solution
|
## Solution
|
||||||
@ -62,4 +58,5 @@ console.log(Kitten.next);
|
|||||||
```js
|
```js
|
||||||
// solution required
|
// solution required
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
Reference in New Issue
Block a user