chore(learn): Applied MDX format to Chinese curriculum files (#40462)
This commit is contained in:
@ -1,74 +1,94 @@
|
||||
---
|
||||
id: 587d8257367417b2b2512c7b
|
||||
title: 将新元素添加到二叉搜索树
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 将新元素添加到二叉搜索树
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">现在我们已经了解了基础知识,让我们编写一个更复杂的方法。在此挑战中,我们将创建一个向二叉搜索树添加新值的方法。该方法应该被称为<code>add</code> ,它应该接受一个整数值来添加到树中。注意保持二叉搜索树的不变量:每个左子项中的值应小于或等于父值,并且每个右子项中的值应大于或等于父值。在这里,让我们这样做,以便我们的树不能容纳重复的值。如果我们尝试添加已存在的值,则该方法应返回<code>null</code> 。否则,如果添加成功,则应返回<code>undefined</code> 。提示:树是自然递归的数据结构! </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
现在我们已经了解了基础知识,让我们编写一个更复杂的方法。在此挑战中,我们将创建一个向二叉搜索树添加新值的方法。该方法应该被称为`add` ,它应该接受一个整数值来添加到树中。注意保持二叉搜索树的不变量:每个左子项中的值应小于或等于父值,并且每个右子项中的值应大于或等于父值。在这里,让我们这样做,以便我们的树不能容纳重复的值。如果我们尝试添加已存在的值,则该方法应返回`null` 。否则,如果添加成功,则应返回`undefined` 。提示:树是自然递归的数据结构!
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>add</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.add == 'function')})());
|
||||
- text: add方法根据二叉搜索树规则添加元素。
|
||||
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()); })());
|
||||
- text: 添加已存在的元素将返回<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; })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`add`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.add == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
add方法根据二叉搜索树规则添加元素。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
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();
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
添加已存在的元素将返回`null`
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,91 +1,56 @@
|
||||
---
|
||||
id: 587d8252367417b2b2512c67
|
||||
title: 在链接列表中的特定索引处添加元素
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在链接列表中的特定索引处添加元素
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">让我们创建一个addAt(index,element)方法,在给定的索引处添加一个元素。就像我们如何删除给定索引处的元素一样,我们需要在遍历链表时跟踪currentIndex。当currentIndex与给定索引匹配时,我们需要重新分配上一个节点的下一个属性以引用新添加的节点。并且新节点应该引用currentIndex中的下一个节点。回到康加线的例子,一个新人想加入这条线,但他想加入中间。你处于中间位置,所以你要把手从你前面的人身上移开。新人走过去,把手放在你曾经牵过手的那个人身上,现在你已经掌握了新人。说明创建addAt(index,element)方法,该方法在给定索引处添加元素。如果无法添加元素,则返回false。注意请记住检查给定索引是否为负数或者是否长于链接列表的长度。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
让我们创建一个addAt(index,element)方法,在给定的索引处添加一个元素。就像我们如何删除给定索引处的元素一样,我们需要在遍历链表时跟踪currentIndex。当currentIndex与给定索引匹配时,我们需要重新分配上一个节点的下一个属性以引用新添加的节点。并且新节点应该引用currentIndex中的下一个节点。回到康加线的例子,一个新人想加入这条线,但他想加入中间。你处于中间位置,所以你要把手从你前面的人身上移开。新人走过去,把手放在你曾经牵过手的那个人身上,现在你已经掌握了新人。说明创建addAt(index,element)方法,该方法在给定索引处添加元素。如果无法添加元素,则返回false。注意请记住检查给定索引是否为负数或者是否长于链接列表的长度。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 当给定索引为0时, <code>addAt</code>方法应重新分配<code>head</code>到新节点。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); test.addAt(0,'cat'); return test.head().element === 'cat'}()));
|
||||
- text: 对于添加到链接列表的每个新节点, <code>addAt</code>方法应该将链表的长度增加一。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); test.addAt(0,'cat'); return test.size() === 3}()));
|
||||
- text: 如果无法添加节点,则<code>addAt</code>方法应返回<code>false</code> 。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); return (test.addAt(4,'cat') === false); }()));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
当给定索引为0时, `addAt`方法应重新分配`head`到新节点。
|
||||
|
||||
```js
|
||||
function LinkedList() {
|
||||
var length = 0;
|
||||
var head = null;
|
||||
|
||||
var Node = function(element){
|
||||
this.element = element;
|
||||
this.next = null;
|
||||
};
|
||||
|
||||
this.size = function(){
|
||||
return length;
|
||||
};
|
||||
|
||||
this.head = function(){
|
||||
return head;
|
||||
};
|
||||
|
||||
this.add = function(element){
|
||||
var node = new Node(element);
|
||||
if (head === null){
|
||||
head = node;
|
||||
} else {
|
||||
var currentNode = head;
|
||||
|
||||
while (currentNode.next) {
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
|
||||
currentNode.next = node;
|
||||
}
|
||||
length++;
|
||||
};
|
||||
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.addAt(0, 'cat');
|
||||
return test.head().element === 'cat';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
对于添加到链接列表的每个新节点, `addAt`方法应该将链表的长度增加一。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.addAt(0, 'cat');
|
||||
return test.size() === 3;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
如果无法添加节点,则`addAt`方法应返回`false` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
return test.addAt(4, 'cat') === false;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,56 +1,72 @@
|
||||
---
|
||||
id: 587d8256367417b2b2512c77
|
||||
title: 邻接名单
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 邻接名单
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">图表可以以不同方式表示。这里我们描述一种方法,称为<dfn>邻接列表</dfn> 。邻接列表本质上是项目符号列表,其中左侧是节点,右侧列出它所连接的所有其他节点。下面是邻接列表的表示。 <blockquote> Node1:Node2,Node3 <br> Node2:Node1 <br> Node3:Node1 </blockquote>以上是无向图,因为<code>Node1</code>连接到<code>Node2</code>和<code>Node3</code> ,并且该信息与<code>Node2</code>和<code>Node3</code>显示的连接一致。有向图的邻接列表意味着列表的每一行都显示方向。如果指示上述内容,那么<code>Node2: Node1</code>将意味着有向边缘从<code>Node2</code>指向<code>Node1</code> 。我们可以将上面的无向图表示为邻接列表,方法是将其放在JavaScript对象中。 <blockquote> var undirectedG = { <br>节点1:[“Node2”,“Node3”], <br> Node2:[“Node1”], <br> Node3:[“Node1”] <br> }; </blockquote>这也可以更简单地表示为一个数组,其中节点只有数字而不是字符串标签。 <blockquote> var undirectedGArr = [ <br> [1,2],#Node1 <br> [0],#Node2 <br> [0] #Node3 <br> ]。 </blockquote></section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建一个社交网络作为无向图,其中有4个节点/人名为<code>James</code> , <code>Jill</code> , <code>Jenny</code>和<code>Jeff</code> 。詹姆斯和杰夫,吉尔和珍妮以及杰夫和珍妮之间存在边缘/关系。 </section>
|
||||
图表可以以不同方式表示。这里我们描述一种方法,称为<dfn>邻接列表</dfn> 。邻接列表本质上是项目符号列表,其中左侧是节点,右侧列出它所连接的所有其他节点。下面是邻接列表的表示。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> Node1:Node2,Node3
|
||||
> Node2:Node1
|
||||
> Node3:Node1
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>undirectedAdjList</code>应该只包含四个节点。
|
||||
testString: assert(Object.keys(undirectedAdjList).length === 4);
|
||||
- text: <code>Jeff</code>和<code>James</code>之间应该有优势。
|
||||
testString: assert(undirectedAdjList.James.indexOf("Jeff") !== -1 && undirectedAdjList.Jeff.indexOf("James") !== -1);
|
||||
- text: <code>Jill</code>和<code>Jenny</code>之间应该有一个优势。
|
||||
testString: assert(undirectedAdjList.Jill.indexOf("Jenny") !== -1 && undirectedAdjList.Jill.indexOf("Jenny") !== -1);
|
||||
- text: <code>Jeff</code>和<code>Jenny</code>之间应该有优势。
|
||||
testString: assert(undirectedAdjList.Jeff.indexOf("Jenny") !== -1 && undirectedAdjList.Jenny.indexOf("Jeff") !== -1);
|
||||
以上是无向图,因为`Node1`连接到`Node2`和`Node3` ,并且该信息与`Node2`和`Node3`显示的连接一致。有向图的邻接列表意味着列表的每一行都显示方向。如果指示上述内容,那么`Node2: Node1`将意味着有向边缘从`Node2`指向`Node1` 。我们可以将上面的无向图表示为邻接列表,方法是将其放在JavaScript对象中。
|
||||
|
||||
```
|
||||
> var undirectedG = {
|
||||
> 节点1:\[“Node2”,“Node3”],
|
||||
> Node2:\[“Node1”],
|
||||
> Node3:\[“Node1”]
|
||||
> };
|
||||
|
||||
</section>
|
||||
这也可以更简单地表示为一个数组,其中节点只有数字而不是字符串标签。
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
> var undirectedGArr = \[
|
||||
> \[1,2],#Node1
|
||||
> \[0],#Node2
|
||||
> \[0] #Node3
|
||||
> ]。
|
||||
|
||||
<div id='js-seed'>
|
||||
# --instructions--
|
||||
|
||||
创建一个社交网络作为无向图,其中有4个节点/人名为`James` , `Jill` , `Jenny`和`Jeff` 。詹姆斯和杰夫,吉尔和珍妮以及杰夫和珍妮之间存在边缘/关系。
|
||||
|
||||
# --hints--
|
||||
|
||||
`undirectedAdjList`应该只包含四个节点。
|
||||
|
||||
```js
|
||||
var undirectedAdjList = {
|
||||
};
|
||||
|
||||
assert(Object.keys(undirectedAdjList).length === 4);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`Jeff`和`James`之间应该有优势。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
undirectedAdjList.James.indexOf('Jeff') !== -1 &&
|
||||
undirectedAdjList.Jeff.indexOf('James') !== -1
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
`Jill`和`Jenny`之间应该有一个优势。
|
||||
|
||||
```js
|
||||
assert(
|
||||
undirectedAdjList.Jill.indexOf('Jenny') !== -1 &&
|
||||
undirectedAdjList.Jill.indexOf('Jenny') !== -1
|
||||
);
|
||||
```
|
||||
|
||||
`Jeff`和`Jenny`之间应该有优势。
|
||||
|
||||
```js
|
||||
assert(
|
||||
undirectedAdjList.Jeff.indexOf('Jenny') !== -1 &&
|
||||
undirectedAdjList.Jenny.indexOf('Jeff') !== -1
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,58 +1,92 @@
|
||||
---
|
||||
id: 587d8256367417b2b2512c78
|
||||
title: 邻接矩阵
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 邻接矩阵
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">表示图形的另一种方法是将其置于<dfn>邻接矩阵中</dfn> 。 <dfn>邻接矩阵</dfn>是二维(2D)阵列,其中每个嵌套数组具有与外部数组相同数量的元素。换句话说,它是数字的矩阵或网格,其中数字代表边缘。零意味着没有边缘或关系。 <blockquote> 1 2 3 <br> ------ <br> 1 | 0 1 1 <br> 2 | 1 0 0 <br> 3 | 1 0 0 </blockquote>上面是一个非常简单的无向图,其中有三个节点,第一个节点连接到第二个和第三个节点。 <strong>注意</strong> :矩阵顶部和左侧的数字只是节点的标签。下面是同一件事的JavaScript实现。 <blockquote> var adjMat = [ <br> [0,1,1], <br> [1,0,0], <br> [1,0,0] <br> ]。 </blockquote>与邻接列表不同,矩阵的每个“行”必须具有与图中的节点相同数量的元素。这里我们有一个三乘三矩阵,这意味着我们的图中有三个节点。有向图看起来很相似。下面是第一节点具有指向第二节点的边缘,然后第二节点具有指向第三节点的边缘的图。 <blockquote> var adjMatDirected = [ <br> [0,1,0], <br> [0,0,1], <br> [0,0,0] <br> ]。 </blockquote>图形的边缘也可以有权<dfn>重</dfn> 。到目前为止,我们有<dfn>未加权的</dfn>边缘,只有存在和缺少边是二进制( <code>0</code>或<code>1</code> )。根据您的应用,您可以拥有不同的重量。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建具有五个节点的无向图的邻接矩阵。该矩阵应该是多维数组。这五个节点在第一和第四节点,第一和第三节点,第三和第五节点以及第四和第五节点之间具有关系。所有边缘权重都是一个。 </section>
|
||||
表示图形的另一种方法是将其置于<dfn>邻接矩阵中</dfn> 。 <dfn>邻接矩阵</dfn>是二维(2D)阵列,其中每个嵌套数组具有与外部数组相同数量的元素。换句话说,它是数字的矩阵或网格,其中数字代表边缘。零意味着没有边缘或关系。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> 1 2 3
|
||||
>
|
||||
> * * *
|
||||
>
|
||||
> 1 | 0 1 1
|
||||
> 2 | 1 0 0
|
||||
> 3 | 1 0 0
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>undirectedAdjList</code>应该只包含五个节点。
|
||||
testString: assert((adjMatUndirected.length === 5) && adjMatUndirected.map(function(x) { return x.length === 5 }).reduce(function(a, b) { return a && b }) );
|
||||
- text: 第一个和第四个节点之间应该有一条边。
|
||||
testString: assert((adjMatUndirected[0][3] === 1) && (adjMatUndirected[3][0] === 1));
|
||||
- text: 第一个和第三个节点之间应该有一条边。
|
||||
testString: assert((adjMatUndirected[0][2] === 1) && (adjMatUndirected[2][0] === 1));
|
||||
- text: 第三个和第五个节点之间应该有一条边。
|
||||
testString: assert((adjMatUndirected[2][4] === 1) && (adjMatUndirected[4][2] === 1));
|
||||
- text: 第四个和第五个节点之间应该有一条边。
|
||||
testString: assert((adjMatUndirected[3][4] === 1) && (adjMatUndirected[4][3] === 1));
|
||||
上面是一个非常简单的无向图,其中有三个节点,第一个节点连接到第二个和第三个节点。 **注意** :矩阵顶部和左侧的数字只是节点的标签。下面是同一件事的JavaScript实现。
|
||||
|
||||
```
|
||||
> var adjMat = \[
|
||||
> \[0,1,1],
|
||||
> \[1,0,0],
|
||||
> \[1,0,0]
|
||||
> ]。
|
||||
|
||||
</section>
|
||||
与邻接列表不同,矩阵的每个“行”必须具有与图中的节点相同数量的元素。这里我们有一个三乘三矩阵,这意味着我们的图中有三个节点。有向图看起来很相似。下面是第一节点具有指向第二节点的边缘,然后第二节点具有指向第三节点的边缘的图。
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
> var adjMatDirected = \[
|
||||
> \[0,1,0],
|
||||
> \[0,0,1],
|
||||
> \[0,0,0]
|
||||
> ]。
|
||||
|
||||
<div id='js-seed'>
|
||||
图形的边缘也可以有权
|
||||
|
||||
<dfn>重</dfn>
|
||||
|
||||
。到目前为止,我们有
|
||||
|
||||
<dfn>未加权的</dfn>
|
||||
|
||||
边缘,只有存在和缺少边是二进制( `0`或`1` )。根据您的应用,您可以拥有不同的重量。
|
||||
|
||||
# --instructions--
|
||||
|
||||
创建具有五个节点的无向图的邻接矩阵。该矩阵应该是多维数组。这五个节点在第一和第四节点,第一和第三节点,第三和第五节点以及第四和第五节点之间具有关系。所有边缘权重都是一个。
|
||||
|
||||
# --hints--
|
||||
|
||||
`undirectedAdjList`应该只包含五个节点。
|
||||
|
||||
```js
|
||||
var adjMatUndirected = [
|
||||
];
|
||||
|
||||
assert(
|
||||
adjMatUndirected.length === 5 &&
|
||||
adjMatUndirected
|
||||
.map(function (x) {
|
||||
return x.length === 5;
|
||||
})
|
||||
.reduce(function (a, b) {
|
||||
return a && b;
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
第一个和第四个节点之间应该有一条边。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(adjMatUndirected[0][3] === 1 && adjMatUndirected[3][0] === 1);
|
||||
```
|
||||
|
||||
/section>
|
||||
第一个和第三个节点之间应该有一条边。
|
||||
|
||||
```js
|
||||
assert(adjMatUndirected[0][2] === 1 && adjMatUndirected[2][0] === 1);
|
||||
```
|
||||
|
||||
第三个和第五个节点之间应该有一条边。
|
||||
|
||||
```js
|
||||
assert(adjMatUndirected[2][4] === 1 && adjMatUndirected[4][2] === 1);
|
||||
```
|
||||
|
||||
第四个和第五个节点之间应该有一条边。
|
||||
|
||||
```js
|
||||
assert(adjMatUndirected[3][4] === 1 && adjMatUndirected[4][3] === 1);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,76 +1,85 @@
|
||||
---
|
||||
id: 587d825c367417b2b2512c90
|
||||
title: 广度优先搜索
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 广度优先搜索
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">到目前为止,我们已经学会了创建图表表示的不同方法。现在怎么办?一个自然的问题是图中任何两个节点之间的距离是多少?输入<dfn>图遍历算法</dfn> 。 <dfn>遍历算法</dfn>是遍历或访问图中节点的算法。一种遍历算法是广度优先搜索算法。该算法从一个节点开始,首先访问一个边缘的所有邻居,然后继续访问它们的每个邻居。在视觉上,这就是算法正在做的事情。 <img class="img-responsive" src="https://camo.githubusercontent.com/2f57e6239884a1a03402912f13c49555dec76d06/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f342f34362f416e696d617465645f4246532e676966">要实现此算法,您需要输入图形结构和要启动的节点。首先,您需要了解距起始节点的距离。这个你想要开始你所有的距离最初一些大的数字,如<code>Infinity</code> 。这为从起始节点无法访问节点的情况提供了参考。接下来,您将要从开始节点转到其邻居。这些邻居是一个边缘,此时你应该添加一个距离单位到你要跟踪的距离。最后,有助于实现广度优先搜索算法的重要数据结构是队列。这是一个数组,您可以在其中添加元素到一端并从另一端删除元素。这也称为<dfn>FIFO</dfn>或<dfn>先进先出</dfn>数据结构。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">编写一个函数<code>bfs()</code> ,它将邻接矩阵图(二维数组)和节点标签根作为参数。节点标签只是<code>0</code>到<code>n - 1</code>之间节点的整数值,其中<code>n</code>是图中节点的总数。您的函数将输出JavaScript对象键值对与节点及其与根的距离。如果无法到达节点,则其距离应为<code>Infinity</code> 。 </section>
|
||||
到目前为止,我们已经学会了创建图表表示的不同方法。现在怎么办?一个自然的问题是图中任何两个节点之间的距离是多少?输入<dfn>图遍历算法</dfn> 。 <dfn>遍历算法</dfn>是遍历或访问图中节点的算法。一种遍历算法是广度优先搜索算法。该算法从一个节点开始,首先访问一个边缘的所有邻居,然后继续访问它们的每个邻居。在视觉上,这就是算法正在做的事情。 要实现此算法,您需要输入图形结构和要启动的节点。首先,您需要了解距起始节点的距离。这个你想要开始你所有的距离最初一些大的数字,如`Infinity` 。这为从起始节点无法访问节点的情况提供了参考。接下来,您将要从开始节点转到其邻居。这些邻居是一个边缘,此时你应该添加一个距离单位到你要跟踪的距离。最后,有助于实现广度优先搜索算法的重要数据结构是队列。这是一个数组,您可以在其中添加元素到一端并从另一端删除元素。这也称为<dfn>FIFO</dfn>或<dfn>先进先出</dfn>数据结构。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>1</code>应该返回<code>{0: 1, 1: 0, 2: 1, 3: 2}</code>'
|
||||
testString: 'assert((function() { var graph = [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]; var results = bfs(graph, 1); return isEquivalent(results, {0: 1, 1: 0, 2: 1, 3: 2})})());'
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]</code> ,起始节点为<code>1</code>应该返回<code>{0: 1, 1: 0, 2: 1, 3: Infinity}</code>'
|
||||
testString: 'assert((function() { var graph = [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]; var results = bfs(graph, 1); return isEquivalent(results, {0: 1, 1: 0, 2: 1, 3: Infinity})})());'
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>0</code>应该返回<code>{0: 0, 1: 1, 2: 2, 3: 3}</code>'
|
||||
testString: 'assert((function() { var graph = [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]; var results = bfs(graph, 0); return isEquivalent(results, {0: 0, 1: 1, 2: 2, 3: 3})})());'
|
||||
- text: '起始节点为<code>0</code>的输入图<code>[[0, 1], [1, 0]]</code>应返回<code>{0: 0, 1: 1}</code>'
|
||||
testString: 'assert((function() { var graph = [[0, 1], [1, 0]]; var results = bfs(graph, 0); return isEquivalent(results, {0: 0, 1: 1})})());'
|
||||
编写一个函数`bfs()` ,它将邻接矩阵图(二维数组)和节点标签根作为参数。节点标签只是`0`到`n - 1`之间节点的整数值,其中`n`是图中节点的总数。您的函数将输出JavaScript对象键值对与节点及其与根的距离。如果无法到达节点,则其距离应为`Infinity` 。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` ,起始节点为`1`应该返回`{0: 1, 1: 0, 2: 1, 3: 2}`
|
||||
|
||||
```js
|
||||
function bfs(graph, root) {
|
||||
// Distance object returned
|
||||
var nodesLen = {};
|
||||
|
||||
return nodesLen;
|
||||
};
|
||||
|
||||
var exBFSGraph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
console.log(bfs(exBFSGraph, 3));
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
var results = bfs(graph, 1);
|
||||
return isEquivalent(results, { 0: 1, 1: 0, 2: 1, 3: 2 });
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` ,起始节点为`1`应该返回`{0: 1, 1: 0, 2: 1, 3: Infinity}`
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 0, 0]
|
||||
];
|
||||
var results = bfs(graph, 1);
|
||||
return isEquivalent(results, { 0: 1, 1: 0, 2: 1, 3: Infinity });
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` ,起始节点为`0`应该返回`{0: 0, 1: 1, 2: 2, 3: 3}`
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
var results = bfs(graph, 0);
|
||||
return isEquivalent(results, { 0: 0, 1: 1, 2: 2, 3: 3 });
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
起始节点为`0`的输入图`[[0, 1], [1, 0]]`应返回`{0: 0, 1: 1}`
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1],
|
||||
[1, 0]
|
||||
];
|
||||
var results = bfs(graph, 0);
|
||||
return isEquivalent(results, { 0: 0, 1: 1 });
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,74 +1,92 @@
|
||||
---
|
||||
id: 587d8257367417b2b2512c7c
|
||||
title: 检查二进制搜索树中是否存在元素
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 检查二进制搜索树中是否存在元素
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">现在我们对二进制搜索树有了一般意义,让我们更详细地讨论它。二进制搜索树为平均情况下的查找,插入和删除的常见操作提供对数时间,并且在最坏情况下提供线性时间。为什么是这样?这些基本操作中的每一个都要求我们在树中找到一个项目(或者在插入的情况下找到它应该去的地方),并且由于每个父节点处的树结构,我们向左或向右分支并且有效地排除了一半的大小剩下的树。这使得搜索与树中节点数的对数成比例,这在平均情况下为这些操作创建对数时间。好的,但最坏的情况呢?那么,可考虑从以下值建构一棵树,将它们从左至右: <code>10</code> , <code>12</code> , <code>17</code> , <code>25</code> 。根据我们的规则二叉搜索树,我们将增加<code>12</code>到右侧<code>10</code> , <code>17</code> ,以这样的权利,以及<code>25</code>到这一权利。现在我们的树类似于一个链表,并且遍历它以找到<code>25</code>将要求我们以线性方式遍历所有项目。因此,在最坏的情况下,线性时间。这里的问题是树是不平衡的。我们将更多地了解这在以下挑战中意味着什么。说明:在此挑战中,我们将为树创建一个实用程序。编写一个方法<code>isPresent</code> ,它接受一个整数值作为输入,并在二叉搜索树中返回该值是否存在的布尔值。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
现在我们对二进制搜索树有了一般意义,让我们更详细地讨论它。二进制搜索树为平均情况下的查找,插入和删除的常见操作提供对数时间,并且在最坏情况下提供线性时间。为什么是这样?这些基本操作中的每一个都要求我们在树中找到一个项目(或者在插入的情况下找到它应该去的地方),并且由于每个父节点处的树结构,我们向左或向右分支并且有效地排除了一半的大小剩下的树。这使得搜索与树中节点数的对数成比例,这在平均情况下为这些操作创建对数时间。好的,但最坏的情况呢?那么,可考虑从以下值建构一棵树,将它们从左至右: `10` , `12` , `17` , `25` 。根据我们的规则二叉搜索树,我们将增加`12`到右侧`10` , `17` ,以这样的权利,以及`25`到这一权利。现在我们的树类似于一个链表,并且遍历它以找到`25`将要求我们以线性方式遍历所有项目。因此,在最坏的情况下,线性时间。这里的问题是树是不平衡的。我们将更多地了解这在以下挑战中意味着什么。说明:在此挑战中,我们将为树创建一个实用程序。编写一个方法`isPresent` ,它接受一个整数值作为输入,并在二叉搜索树中返回该值是否存在的布尔值。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>isPresent</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.isPresent == 'function')})());
|
||||
- text: <code>isPresent</code>方法正确检查添加到树中的元素是否存在。
|
||||
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) ); })());
|
||||
- text: <code>isPresent</code>处理树为空的情况。
|
||||
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; })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`isPresent`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.isPresent == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`isPresent`方法正确检查添加到树中的元素是否存在。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
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)
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
`isPresent`处理树为空的情况。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -0,0 +1,135 @@
|
||||
---
|
||||
id: 5cc0c1b32479e176caf3b422
|
||||
title: Check if Tree is Binary Search Tree
|
||||
challengeType: 1
|
||||
forumTopicId: 301624
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Since you already know what a binary search tree is, this challenge will establish how it is you can tell that a tree is a binary search tree or not.
|
||||
|
||||
The main distinction of a binary search tree is that the nodes are ordered in an organized fashion. Nodes have at most 2 child nodes (placed to the right and/or left) based on if the child node's value is greater than or equal to (right) or less than (left) the parent node.
|
||||
|
||||
# --instructions--
|
||||
|
||||
In this challenge, you will create a utility for your tree. Write a JavaScript method `isBinarySearchTree` which takes a tree as an input and returns a boolean value for whether the tree is a binary search tree or not. Use recursion whenever possible.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your Binary Search Tree should return true when checked with `isBinarySearchTree()`.
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
test.push(1);
|
||||
test.push(5);
|
||||
test.push(3);
|
||||
test.push(2);
|
||||
test.push(4);
|
||||
return isBinarySearchTree(test) == true;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --after-user-code--
|
||||
|
||||
```js
|
||||
BinarySearchTree.prototype.push = function(val) {
|
||||
var root = this.root;
|
||||
|
||||
if (!root) {
|
||||
this.root = new Node(val);
|
||||
return;
|
||||
}
|
||||
|
||||
var currentNode = root;
|
||||
var newNode = new Node(val);
|
||||
|
||||
while (currentNode) {
|
||||
if (val < currentNode.value) {
|
||||
if (!currentNode.left) {
|
||||
currentNode.left = newNode;
|
||||
break;
|
||||
} else {
|
||||
currentNode = currentNode.left;
|
||||
}
|
||||
} else {
|
||||
if (!currentNode.right) {
|
||||
currentNode.right = newNode;
|
||||
break;
|
||||
} else {
|
||||
currentNode = currentNode.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
}
|
||||
function isBinarySearchTree(tree) {
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
}
|
||||
function isBinarySearchTree(tree) {
|
||||
if (tree.root == null) {
|
||||
return null;
|
||||
} else {
|
||||
let isBST = true;
|
||||
function checkTree(node) {
|
||||
if (node.left != null) {
|
||||
const left = node.left;
|
||||
if (left.value > node.value) {
|
||||
isBST = false;
|
||||
} else {
|
||||
checkTree(left);
|
||||
}
|
||||
}
|
||||
if (node.right != null) {
|
||||
const right = node.right;
|
||||
if (right.value < node.value) {
|
||||
isBST = false;
|
||||
} else {
|
||||
checkTree(right);
|
||||
}
|
||||
}
|
||||
}
|
||||
checkTree(tree.root);
|
||||
return isBST;
|
||||
}
|
||||
};
|
||||
```
|
@ -1,89 +1,129 @@
|
||||
---
|
||||
id: 587d8255367417b2b2512c75
|
||||
title: 创建循环队列
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建循环队列
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在此挑战中,您将创建一个循环队列。循环队列基本上是一个写入集合末尾的队列,然后开始在集合开头写自己。这种类型的数据结构在某些情况下具有一些有用的应用。例如,循环队列可用于流媒体。队列填满后,新媒体数据就会开始覆盖旧数据。说明这个概念的一个好方法是使用数组: <blockquote> [1,2,3,4,5] <br> ^读@ 0 <br> ^写@ 0 </blockquote>这里的读写都在<code>0</code> 。现在队列获得3个新记录<code>a</code> , <code>b</code>和<code>c</code> 。我们的队列现在看起来像: <blockquote> [a,b,c,4,5] <br> ^读@ 0 <br> ^写@ 3 </blockquote>当读头读取时,它可以删除值或保留它们: <blockquote> [null,null,null,4,5] <br> ^阅读@ 3 <br> ^写@ 3 </blockquote>一旦写入到达数组的末尾,它就会循环回到开头: <blockquote> [f,null,null,d,e] <br> ^阅读@ 3 <br> ^写@ 1 </blockquote>这种方法需要恒定的内存量,但允许处理更大尺寸的文件。说明:在此挑战中,我们将实现循环队列。循环队列应提供<code>enqueue</code>和<code>dequeue</code>方法,允许您读取和写入队列。类本身也应该接受一个整数,您可以使用该整数在创建队列时指定队列的大小。我们已经在代码编辑器中为您编写了此类的起始版本。将项目排入队列时,写入指针应向前推进,并在到达队列末尾时循环回到开头。同样,当您使项目出列时,读指针应向前推进。不应允许写指针移过读指针(我们的类不会让你覆盖你还没有读过的数据),并且读指针不能超过你写的数据。此外,如果成功,则<code>enqueue</code>方法应返回您入<code>enqueue</code>的项,否则返回<code>null</code> 。类似地,当你使一个项目出列时,它应该被返回,如果你不能出列,你应该返回<code>null</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在此挑战中,您将创建一个循环队列。循环队列基本上是一个写入集合末尾的队列,然后开始在集合开头写自己。这种类型的数据结构在某些情况下具有一些有用的应用。例如,循环队列可用于流媒体。队列填满后,新媒体数据就会开始覆盖旧数据。说明这个概念的一个好方法是使用数组:
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> \[1,2,3,4,5]
|
||||
> ^读@ 0
|
||||
> ^写@ 0
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>enqueue</code>方法将项添加到循环队列。
|
||||
testString: assert((function(){ var test = new CircularQueue(3); test.enqueue(17); test.enqueue(32); test.enqueue(591); var print = test.print(); return print[0] === 17 && print[1] === 32 && print[2] === 591; })());
|
||||
- text: 您不能通过读指针将项排入队列。
|
||||
testString: assert((function(){ var test = new CircularQueue(3); test.enqueue(17); test.enqueue(32); test.enqueue(591); test.enqueue(13); test.enqueue(25); test.enqueue(59); var print = test.print(); return print[0] === 17 && print[1] === 32 && print[2] === 591; })());
|
||||
- text: <code>dequeue</code>方法使队列中的项目出列。
|
||||
testString: assert((function(){ var test = new CircularQueue(3); test.enqueue(17); test.enqueue(32); test.enqueue(591); return test.dequeue() === 17 && test.dequeue() === 32 && test.dequeue() === 591; })());
|
||||
- text: 项目出列后,其队列中的位置应重置为<code>null</code> 。
|
||||
testString: assert((function(){ var test = new CircularQueue(3); test.enqueue(17); test.enqueue(32); test.enqueue(672); test.dequeue(); test.dequeue(); var print = test.print(); return print[0] === null && print[1] === null && print[2] === 672; })());
|
||||
- text: 尝试通过写指针出列队列返回<code>null</code>并且不会使写指针前进。
|
||||
testString: assert((function(){ var test = new CircularQueue(3); test.enqueue(17); test.enqueue(32); test.enqueue(591); return test.dequeue() === 17 && test.dequeue() === 32 && test.dequeue() === 591 && test.dequeue() === null && test.dequeue() === null && test.dequeue() === null && test.dequeue() === null && test.enqueue(100) === 100 && test.dequeue() === 100; })());
|
||||
这里的读写都在`0` 。现在队列获得3个新记录`a` , `b`和`c` 。我们的队列现在看起来像:
|
||||
|
||||
```
|
||||
> \[a,b,c,4,5]
|
||||
> ^读@ 0
|
||||
> ^写@ 3
|
||||
|
||||
</section>
|
||||
当读头读取时,它可以删除值或保留它们:
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
> \[null,null,null,4,5]
|
||||
> ^阅读@ 3
|
||||
> ^写@ 3
|
||||
|
||||
<div id='js-seed'>
|
||||
一旦写入到达数组的末尾,它就会循环回到开头:
|
||||
|
||||
> \[f,null,null,d,e]
|
||||
> ^阅读@ 3
|
||||
> ^写@ 1
|
||||
|
||||
这种方法需要恒定的内存量,但允许处理更大尺寸的文件。说明:在此挑战中,我们将实现循环队列。循环队列应提供`enqueue`和`dequeue`方法,允许您读取和写入队列。类本身也应该接受一个整数,您可以使用该整数在创建队列时指定队列的大小。我们已经在代码编辑器中为您编写了此类的起始版本。将项目排入队列时,写入指针应向前推进,并在到达队列末尾时循环回到开头。同样,当您使项目出列时,读指针应向前推进。不应允许写指针移过读指针(我们的类不会让你覆盖你还没有读过的数据),并且读指针不能超过你写的数据。此外,如果成功,则`enqueue`方法应返回您入`enqueue`的项,否则返回`null` 。类似地,当你使一个项目出列时,它应该被返回,如果你不能出列,你应该返回`null` 。
|
||||
|
||||
# --hints--
|
||||
|
||||
`enqueue`方法将项添加到循环队列。
|
||||
|
||||
```js
|
||||
class CircularQueue {
|
||||
constructor(size) {
|
||||
|
||||
this.queue = [];
|
||||
this.read = 0;
|
||||
this.write = 0;
|
||||
this.max = size - 1;
|
||||
|
||||
while (size > 0) {
|
||||
this.queue.push(null);
|
||||
size--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
print() {
|
||||
return this.queue;
|
||||
}
|
||||
|
||||
|
||||
enqueue(item) {
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
|
||||
dequeue() {
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new CircularQueue(3);
|
||||
test.enqueue(17);
|
||||
test.enqueue(32);
|
||||
test.enqueue(591);
|
||||
var print = test.print();
|
||||
return print[0] === 17 && print[1] === 32 && print[2] === 591;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您不能通过读指针将项排入队列。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new CircularQueue(3);
|
||||
test.enqueue(17);
|
||||
test.enqueue(32);
|
||||
test.enqueue(591);
|
||||
test.enqueue(13);
|
||||
test.enqueue(25);
|
||||
test.enqueue(59);
|
||||
var print = test.print();
|
||||
return print[0] === 17 && print[1] === 32 && print[2] === 591;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
`dequeue`方法使队列中的项目出列。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new CircularQueue(3);
|
||||
test.enqueue(17);
|
||||
test.enqueue(32);
|
||||
test.enqueue(591);
|
||||
return (
|
||||
test.dequeue() === 17 && test.dequeue() === 32 && test.dequeue() === 591
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
项目出列后,其队列中的位置应重置为`null` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new CircularQueue(3);
|
||||
test.enqueue(17);
|
||||
test.enqueue(32);
|
||||
test.enqueue(672);
|
||||
test.dequeue();
|
||||
test.dequeue();
|
||||
var print = test.print();
|
||||
return print[0] === null && print[1] === null && print[2] === 672;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
尝试通过写指针出列队列返回`null`并且不会使写指针前进。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new CircularQueue(3);
|
||||
test.enqueue(17);
|
||||
test.enqueue(32);
|
||||
test.enqueue(591);
|
||||
return (
|
||||
test.dequeue() === 17 &&
|
||||
test.dequeue() === 32 &&
|
||||
test.dequeue() === 591 &&
|
||||
test.dequeue() === null &&
|
||||
test.dequeue() === null &&
|
||||
test.dequeue() === null &&
|
||||
test.dequeue() === null &&
|
||||
test.enqueue(100) === 100 &&
|
||||
test.dequeue() === 100
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,81 +1,151 @@
|
||||
---
|
||||
id: 587d825a367417b2b2512c87
|
||||
title: 创建双向链接列表
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建双向链接列表
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">到目前为止,我们创建的所有链接列表都是单链表。在这里,我们将创建一个<dfn>双向链表</dfn> 。顾名思义,双向链表中的节点引用了列表中的下一个和上一个节点。这允许我们在两个方向上遍历列表,但它还需要使用更多内存,因为每个节点必须包含对列表中前一个节点的附加引用。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">我们提供了一个<code>Node</code>对象并启动了我们的<code>DoublyLinkedList</code> 。让我们将两个方法添加到名为<code>add</code> and <code>remove</code>双向链表<code>remove</code> 。 <code>add</code>方法应该将给定元素添加到列表中,而<code>remove</code>方法应该删除列表中所有出现的给定元素。编写这些方法时要小心处理任何可能的边缘情况,例如删除第一个或最后一个元素。此外,删除空列表中的任何项应返回<code>null</code> 。 </section>
|
||||
到目前为止,我们创建的所有链接列表都是单链表。在这里,我们将创建一个<dfn>双向链表</dfn> 。顾名思义,双向链表中的节点引用了列表中的下一个和上一个节点。这允许我们在两个方向上遍历列表,但它还需要使用更多内存,因为每个节点必须包含对列表中前一个节点的附加引用。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在DoublyLinkedList数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; return (typeof test == 'object')})());
|
||||
- text: DoublyLinkedList有一个名为add的方法。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; if (test.add == undefined) { return false; }; return (typeof test.add == 'function')})());
|
||||
- text: DoublyLinkedList有一个名为remove的方法。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; if (test.remove == undefined) { return false; }; return (typeof test.remove == 'function')})());
|
||||
- text: 从空列表中删除项目将返回null。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; return (test.remove(100) == null); })());
|
||||
- text: add方法将项添加到列表中。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; test.add(5); test.add(6); test.add(723); return (test.print().join('') == '56723'); })());
|
||||
- text: 每个节点都跟踪前一个节点。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; test.add(50); test.add(68); test.add(73); return (test.printReverse().join('') == '736850'); })());
|
||||
- text: 可以从列表中删除第一个项目。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; test.add(25); test.add(35); test.add(60); test.remove(25); return ( test.print().join('') == '3560' ) })());
|
||||
- text: 最后一项可以从列表中删除。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; test.add(25); test.add(35); test.add(60); test.remove(60); return ( test.print().join('') == '2535' ) })());
|
||||
我们提供了一个`Node`对象并启动了我们的`DoublyLinkedList` 。让我们将两个方法添加到名为`add` and `remove`双向链表`remove` 。 `add`方法应该将给定元素添加到列表中,而`remove`方法应该删除列表中所有出现的给定元素。编写这些方法时要小心处理任何可能的边缘情况,例如删除第一个或最后一个元素。此外,删除空列表中的任何项应返回`null` 。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在DoublyLinkedList数据结构。
|
||||
|
||||
```js
|
||||
var Node = function(data, prev) {
|
||||
this.data = data;
|
||||
this.prev = prev;
|
||||
this.next = null;
|
||||
};
|
||||
var DoublyLinkedList = function() {
|
||||
this.head = null;
|
||||
this.tail = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
DoublyLinkedList有一个名为add的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
if (test.add == undefined) {
|
||||
return false;
|
||||
}
|
||||
return typeof test.add == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
DoublyLinkedList有一个名为remove的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
if (test.remove == undefined) {
|
||||
return false;
|
||||
}
|
||||
return typeof test.remove == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
从空列表中删除项目将返回null。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
return test.remove(100) == null;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
add方法将项添加到列表中。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
test.add(5);
|
||||
test.add(6);
|
||||
test.add(723);
|
||||
return test.print().join('') == '56723';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
每个节点都跟踪前一个节点。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
test.add(50);
|
||||
test.add(68);
|
||||
test.add(73);
|
||||
return test.printReverse().join('') == '736850';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
可以从列表中删除第一个项目。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
test.add(25);
|
||||
test.add(35);
|
||||
test.add(60);
|
||||
test.remove(25);
|
||||
return test.print().join('') == '3560';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
最后一项可以从列表中删除。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
test.add(25);
|
||||
test.add(35);
|
||||
test.add(60);
|
||||
test.remove(60);
|
||||
return test.print().join('') == '2535';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,90 +1,151 @@
|
||||
---
|
||||
id: 587d825b367417b2b2512c8e
|
||||
title: 创建一个哈希表
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建一个哈希表
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在这个挑战中,我们将学习哈希表。哈希表用于实现关联数组或键值对的映射,就像我们刚刚研究的对象和地图一样。例如,JavaScript对象可以实现为哈希表(其实际实现将取决于它运行的环境)。哈希表的工作方式是它接受一个键输入并以确定的方式将此键散列到某个数值。然后将该数值用作存储相关值的实际键。然后,如果您尝试再次访问相同的密钥,则散列函数将处理密钥,返回相同的数字结果,然后将用于查找关联的值。这平均提供非常有效的O(1)查找时间。散列表可以实现为具有散列函数的数组,从而生成指定范围内的数组索引。在这种方法中,数组大小的选择很重要,散列函数也是如此。例如,如果散列函数为两个不同的键生成相同的值,该怎么办?这称为碰撞。处理冲突的一种方法是仅将两个键值对存储在该索引处。然后,在查找其中任何一个时,您将不得不遍历项目桶以找到您要查找的密钥。良好的散列函数可最大限度地减少冲突,从而保持有效的搜索时间。在这里,我们不会关注散列或散列表实现的细节,我们将尝试大致了解它们的工作原理。说明:让我们创建哈希表的基本功能。我们已经创建了一个天真的散列函数供您使用。您可以将字符串值传递给函数哈希,它将返回一个哈希值,您可以将其用作存储键。在this.collection对象中根据此散列值存储项目。创建这三种方法:添加,删除和查找。第一个应该接受一个键值对来添加到哈希表。第二个应该在传递密钥时删除键值对。第三个应该接受一个键并返回相关的值,如果该键不存在则返回null。请务必编写代码以解决冲突! </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在这个挑战中,我们将学习哈希表。哈希表用于实现关联数组或键值对的映射,就像我们刚刚研究的对象和地图一样。例如,JavaScript对象可以实现为哈希表(其实际实现将取决于它运行的环境)。哈希表的工作方式是它接受一个键输入并以确定的方式将此键散列到某个数值。然后将该数值用作存储相关值的实际键。然后,如果您尝试再次访问相同的密钥,则散列函数将处理密钥,返回相同的数字结果,然后将用于查找关联的值。这平均提供非常有效的O(1)查找时间。散列表可以实现为具有散列函数的数组,从而生成指定范围内的数组索引。在这种方法中,数组大小的选择很重要,散列函数也是如此。例如,如果散列函数为两个不同的键生成相同的值,该怎么办?这称为碰撞。处理冲突的一种方法是仅将两个键值对存储在该索引处。然后,在查找其中任何一个时,您将不得不遍历项目桶以找到您要查找的密钥。良好的散列函数可最大限度地减少冲突,从而保持有效的搜索时间。在这里,我们不会关注散列或散列表实现的细节,我们将尝试大致了解它们的工作原理。说明:让我们创建哈希表的基本功能。我们已经创建了一个天真的散列函数供您使用。您可以将字符串值传递给函数哈希,它将返回一个哈希值,您可以将其用作存储键。在this.collection对象中根据此散列值存储项目。创建这三种方法:添加,删除和查找。第一个应该接受一个键值对来添加到哈希表。第二个应该在传递密钥时删除键值对。第三个应该接受一个键并返回相关的值,如果该键不存在则返回null。请务必编写代码以解决冲突!
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在HashTable数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; return (typeof test === 'object')})());
|
||||
- text: HashTable有一个add方法。
|
||||
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; return ((typeof test.add) === 'function')})());
|
||||
- text: HashTable有一个删除方法。
|
||||
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; return ((typeof test.remove) === 'function')})());
|
||||
- text: HashTable有一个查找方法。
|
||||
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; return ((typeof test.lookup) === 'function')})());
|
||||
- text: add方法添加键值对,lookup方法返回与给定键关联的值。
|
||||
testString: assert((function() { var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; test.add('key', 'value'); return (test.lookup('key') === 'value')})());
|
||||
- text: remove方法接受一个键作为输入,并删除关联的键值对。
|
||||
testString: assert((function(){ var test = false; if (typeof HashTable !== 'undefined') { test = new HashTable() }; test.add('key', 'value'); test.remove('key'); test.lookup = function(key){ var theHash = hash(key); if (this.collection.hasOwnProperty(theHash)[key]) { return this.collection[theHash][key]; } return null }; var lookup = test.lookup('key'); test.lookup = null; return (lookup === null)})());
|
||||
- text: 使用哈希函数添加项目。
|
||||
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 && called % 3 === 0)})());
|
||||
- text: 哈希表处理冲突。
|
||||
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')})());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在HashTable数据结构。
|
||||
|
||||
```js
|
||||
var called = 0;
|
||||
var hash = (string) => {
|
||||
called++;
|
||||
var hash = 0;
|
||||
for (var i = 0; i < string.length; i++) { hash += string.charCodeAt(i); }
|
||||
return hash;
|
||||
};
|
||||
var HashTable = function() {
|
||||
this.collection = {};
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof HashTable !== 'undefined') {
|
||||
test = new HashTable();
|
||||
}
|
||||
return typeof test === 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Before Test
|
||||
<div id='js-setup'>
|
||||
HashTable有一个add方法。
|
||||
|
||||
```js
|
||||
var called = 0;
|
||||
var hash = (string) => {
|
||||
called++;
|
||||
var hash = 0;
|
||||
for (var i = 0; i < string.length; i++) { hash += string.charCodeAt(i); };
|
||||
return hash;
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof HashTable !== 'undefined') {
|
||||
test = new HashTable();
|
||||
}
|
||||
return typeof test.add === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
HashTable有一个删除方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof HashTable !== 'undefined') {
|
||||
test = new HashTable();
|
||||
}
|
||||
return typeof test.remove === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
HashTable有一个查找方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof HashTable !== 'undefined') {
|
||||
test = new HashTable();
|
||||
}
|
||||
return typeof test.lookup === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
add方法添加键值对,lookup方法返回与给定键关联的值。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof HashTable !== 'undefined') {
|
||||
test = new HashTable();
|
||||
}
|
||||
test.add('key', 'value');
|
||||
return test.lookup('key') === 'value';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
remove方法接受一个键作为输入,并删除关联的键值对。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof HashTable !== 'undefined') {
|
||||
test = new HashTable();
|
||||
}
|
||||
test.add('key', 'value');
|
||||
test.remove('key');
|
||||
test.lookup = function (key) {
|
||||
var theHash = hash(key);
|
||||
if (this.collection.hasOwnProperty(theHash)[key]) {
|
||||
return this.collection[theHash][key];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var lookup = test.lookup('key');
|
||||
test.lookup = null;
|
||||
return lookup === null;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
使用哈希函数添加项目。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
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 && called % 3 === 0;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
哈希表处理冲突。
|
||||
|
||||
```js
|
||||
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'
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,77 +1,68 @@
|
||||
---
|
||||
id: 587d8251367417b2b2512c62
|
||||
title: 创建链接列表类
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建链接列表类
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">让我们创建一个<code>linked list</code>类。每个链接列表都应该从一些基本属性开始: <code>head</code> (列表中的第一项)和<code>length</code> (列表中的项目数)。有时您会看到链接列表的实现,其中包含列表的最后一个元素的<code>tail</code> ,但是现在我们将坚持使用这两个元素。每当我们向链表添加元素时,我们的<code>length</code>属性应该加1。我们想要一种方法将项添加到链表中,因此我们要创建的第一种方法是<code>add</code>方法。如果我们的列表为空,那么向链表添加一个元素就足够了:我们只是将该元素包装在<code>Node</code>类中,然后将该节点分配给链表的<code>head</code> 。但是如果我们的名单已经有一个或多个成员呢?我们如何在列表中添加元素?回想一下,链表中的每个节点都有一个<code>next</code>属性。要将节点添加到列表,请在列表中找到最后一个节点,并将该节点的最后<code>next</code>属性指向新节点。 (提示:当节点的<code>next</code>属性为<code>null</code>时,您知道已到达链表的末尾。) </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">编写一个add方法,将您推送到链接列表的第一个节点分配给<code>head</code> ;之后,每当添加一个节点时,每个节点都应该由前一个节点的<code>next</code>属性引用。注意每次将元素添加到链接列表时,列表的<code>length</code>应增加1。 </section>
|
||||
让我们创建一个`linked list`类。每个链接列表都应该从一些基本属性开始: `head` (列表中的第一项)和`length` (列表中的项目数)。有时您会看到链接列表的实现,其中包含列表的最后一个元素的`tail` ,但是现在我们将坚持使用这两个元素。每当我们向链表添加元素时,我们的`length`属性应该加1。我们想要一种方法将项添加到链表中,因此我们要创建的第一种方法是`add`方法。如果我们的列表为空,那么向链表添加一个元素就足够了:我们只是将该元素包装在`Node`类中,然后将该节点分配给链表的`head` 。但是如果我们的名单已经有一个或多个成员呢?我们如何在列表中添加元素?回想一下,链表中的每个节点都有一个`next`属性。要将节点添加到列表,请在列表中找到最后一个节点,并将该节点的最后`next`属性指向新节点。 (提示:当节点的`next`属性为`null`时,您知道已到达链表的末尾。)
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>LinkedList</code>类应该有一个<code>add</code>方法。
|
||||
testString: assert((function(){var test = new LinkedList(); return (typeof test.add === 'function')}()));
|
||||
- text: 您的<code>LinkedList</code>类应该为添加的第一个节点分配<code>head</code> 。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); return test.head().element === 'cat'}()));
|
||||
- text: <code>LinkedList</code>类中的上一个<code>node</code>应该引用创建的最新节点。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); return test.head().next.element === 'dog'}()));
|
||||
- text: <code>LinkedList</code>类的<code>size</code>应该等于<code>LinkedList</code>的节点数量。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); return test.size() === 2}()));
|
||||
编写一个add方法,将您推送到链接列表的第一个节点分配给`head` ;之后,每当添加一个节点时,每个节点都应该由前一个节点的`next`属性引用。注意每次将元素添加到链接列表时,列表的`length`应增加1。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`LinkedList`类应该有一个`add`方法。
|
||||
|
||||
```js
|
||||
function LinkedList() {
|
||||
var length = 0;
|
||||
var head = null;
|
||||
|
||||
var Node = function(element){
|
||||
this.element = element;
|
||||
this.next = null;
|
||||
};
|
||||
|
||||
this.head = function(){
|
||||
return head;
|
||||
};
|
||||
|
||||
this.size = function(){
|
||||
return length;
|
||||
};
|
||||
|
||||
this.add = function(element){
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
};
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
return typeof test.add === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的`LinkedList`类应该为添加的第一个节点分配`head` 。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
return test.head().element === 'cat';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
`LinkedList`类中的上一个`node`应该引用创建的最新节点。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
return test.head().next.element === 'dog';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`LinkedList`类的`size`应该等于`LinkedList`的节点数量。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
return test.size() === 2;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,66 +1,161 @@
|
||||
---
|
||||
id: 8d5823c8c441eddfaeb5bdef
|
||||
title: 创建地图数据结构
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建地图数据结构
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">接下来的几个挑战将涵盖地图和哈希表。映射是存储键值对的数据结构。在JavaScript中,我们可以将它们作为对象使用。地图可根据键值快速查找存储的项目,是非常常见且有用的数据结构。说明:让我们开始创建自己的地图。因为JavaScript对象提供了比我们在此处编写的任何内容更有效的地图结构,所以这主要是作为学习练习。但是,JavaScript对象仅向我们提供某些操作。如果我们想定义自定义操作怎么办?使用此处提供的<code>Map</code>对象作为JavaScript <code>object</code>的包装器。在Map对象上创建以下方法和操作: <ul><li> <code>add</code>接受要添加到地图的<code>key, value</code>对。 </li><li> <code>remove</code>接受一个键并删除关联的<code>key, value</code>对</li><li> <code>get</code>接受一个<code>key</code>并返回存储的<code>value</code> </li><li>如果密钥存在<code>has</code>接受<code>key</code>并返回<dfn>true,</dfn>否则返回<dfn>false</dfn> 。 </li><li> <code>values</code>返回地图中所有<code>values</code>的数组</li><li> <code>size</code>返回地图中的项目数</li><li> <code>clear</code>清空地图</li></ul></section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
接下来的几个挑战将涵盖地图和哈希表。映射是存储键值对的数据结构。在JavaScript中,我们可以将它们作为对象使用。地图可根据键值快速查找存储的项目,是非常常见且有用的数据结构。说明:让我们开始创建自己的地图。因为JavaScript对象提供了比我们在此处编写的任何内容更有效的地图结构,所以这主要是作为学习练习。但是,JavaScript对象仅向我们提供某些操作。如果我们想定义自定义操作怎么办?使用此处提供的`Map`对象作为JavaScript `object`的包装器。在Map对象上创建以下方法和操作:
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
- `add`接受要添加到地图的`key, value`对。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在地图数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; return (typeof test == 'object')})());
|
||||
- text: Map对象具有以下方法:add,remove,get,has,values,clear和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')})());"
|
||||
- text: add方法将项添加到地图中。
|
||||
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)})());
|
||||
- text: has方法对于添加的项返回true,对于缺少的项返回false。
|
||||
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add('test','value'); return (test.has('test') && !test.has('false'))})());
|
||||
- text: get方法接受键作为输入并返回关联的值。
|
||||
testString: assert((function() { var test = false; if (typeof Map !== 'undefined') { test = new Map() }; test.add('abc','def'); return (test.get('abc') == 'def')})());
|
||||
- text: values方法将存储在映射中的所有值作为数组中的字符串返回。
|
||||
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)})());
|
||||
- text: clear方法清空映射,size方法返回映射中存在的项目数。
|
||||
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)})());
|
||||
- `remove`接受一个键并删除关联的`key, value`对
|
||||
|
||||
```
|
||||
- `get`接受一个`key`并返回存储的`value`
|
||||
|
||||
</section>
|
||||
- 如果密钥存在`has`接受`key`并返回
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
<dfn>true,</dfn>
|
||||
|
||||
<div id='js-seed'>
|
||||
否则返回
|
||||
|
||||
<dfn>false</dfn>
|
||||
|
||||
。
|
||||
|
||||
- `values`返回地图中所有`values`的数组
|
||||
|
||||
- `size`返回地图中的项目数
|
||||
|
||||
- `clear`清空地图
|
||||
|
||||
# --hints--
|
||||
|
||||
存在地图数据结构。
|
||||
|
||||
```js
|
||||
var Map = function() {
|
||||
this.collection = {};
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof Map !== 'undefined') {
|
||||
test = new Map();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
Map对象具有以下方法:add,remove,get,has,values,clear和size。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
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'
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
add方法将项添加到地图中。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
has方法对于添加的项返回true,对于缺少的项返回false。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof Map !== 'undefined') {
|
||||
test = new Map();
|
||||
}
|
||||
test.add('test', 'value');
|
||||
return test.has('test') && !test.has('false');
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
get方法接受键作为输入并返回关联的值。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof Map !== 'undefined') {
|
||||
test = new Map();
|
||||
}
|
||||
test.add('abc', 'def');
|
||||
return test.get('abc') == 'def';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
values方法将存储在映射中的所有值作为数组中的字符串返回。
|
||||
|
||||
```js
|
||||
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
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
clear方法清空映射,size方法返回映射中存在的项目数。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,70 +1,118 @@
|
||||
---
|
||||
id: 587d8255367417b2b2512c74
|
||||
title: 创建优先级队列类
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建优先级队列类
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在此挑战中,您将创建一个优先级队列。优先级队列是一种特殊类型的队列,其中项目可能具有指定其优先级的附加信息。这可以简单地用整数表示。项目优先级将覆盖确定序列项目已出列的放置顺序。如果具有较高优先级的项目在具有较低优先级的项目之后排队,则较高优先级项目将在所有其他项目之前出列。例如,让我们假设我们有一个包含三个项目的优先级队列: <code>[['kitten', 2], ['dog', 2], ['rabbit', 2]]</code>这里第二个值(整数)表示项目优先级。如果我们将优先级为<code>1</code> <code>['human', 1]</code>排入队列(假设优先级较低,则优先级较低),那么它将成为第一个出列的项目。该集合将是这样的: <code>[['human', 1], ['kitten', 2], ['dog', 2], ['rabbit', 2]]</code> 。我们已经开始在代码编辑器中编写<code>PriorityQueue</code> 。您需要添加一个<code>enqueue</code>方法来添加具有优先级的项目,一个用于删除项目的<code>dequeue</code>方法,一个用于返回队列中项目数量的<code>size</code>方法,一个用于返回队列<code>front</code>元素的<code>front</code>方法,以及最后一个<code>isEmpty</code>方法,如果队列为空则返回<code>true</code> ,否则返回<code>false</code> 。入<code>enqueue</code>应接受上面显示格式的项目( <code>['human', 1]</code> ),其中<code>1</code>表示优先级。 <code>dequeue</code>应该只返回当前项目,而不是其优先级。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在此挑战中,您将创建一个优先级队列。优先级队列是一种特殊类型的队列,其中项目可能具有指定其优先级的附加信息。这可以简单地用整数表示。项目优先级将覆盖确定序列项目已出列的放置顺序。如果具有较高优先级的项目在具有较低优先级的项目之后排队,则较高优先级项目将在所有其他项目之前出列。例如,让我们假设我们有一个包含三个项目的优先级队列: `[['kitten', 2], ['dog', 2], ['rabbit', 2]]`这里第二个值(整数)表示项目优先级。如果我们将优先级为`1` `['human', 1]`排入队列(假设优先级较低,则优先级较低),那么它将成为第一个出列的项目。该集合将是这样的: `[['human', 1], ['kitten', 2], ['dog', 2], ['rabbit', 2]]` 。我们已经开始在代码编辑器中编写`PriorityQueue` 。您需要添加一个`enqueue`方法来添加具有优先级的项目,一个用于删除项目的`dequeue`方法,一个用于返回队列中项目数量的`size`方法,一个用于返回队列`front`元素的`front`方法,以及最后一个`isEmpty`方法,如果队列为空则返回`true` ,否则返回`false` 。入`enqueue`应接受上面显示格式的项目( `['human', 1]` ),其中`1`表示优先级。 `dequeue`应该只返回当前项目,而不是其优先级。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>enqueue</code>方法。
|
||||
testString: assert((function(){var test = new PriorityQueue(); return (typeof test.enqueue === 'function')}()));
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>dequeue</code>方法。
|
||||
testString: assert((function(){var test = new PriorityQueue(); return (typeof test.dequeue === 'function')}()));
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>size</code>方法。
|
||||
testString: assert((function(){var test = new PriorityQueue(); return (typeof test.size === 'function')}()));
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>isEmpty</code>方法。
|
||||
testString: assert((function(){var test = new PriorityQueue(); return (typeof test.isEmpty === 'function')}()));
|
||||
- text: 当项目入队和出列时,您的PriorityQueue应使用<code>size</code>方法正确跟踪当前项目数。
|
||||
testString: assert((function(){var test = new PriorityQueue(); test.enqueue(['David Brown', 2]); test.enqueue(['Jon Snow', 1]); var size1 = test.size(); test.dequeue(); var size2 = test.size(); test.enqueue(['A', 3]); test.enqueue(['B', 3]); test.enqueue(['C', 3]); return (size1 === 2 && size2 === 1 && test.size() === 4)}()));
|
||||
- text: 当队列为空时, <code>isEmpty</code>方法应该返回<code>true</code> 。
|
||||
testString: assert((function(){var test = new PriorityQueue(); test.enqueue(['A', 1]); test.enqueue(['B', 1]); test.dequeue(); var first = test.isEmpty(); test.dequeue(); return (!first && test.isEmpty()); }()));
|
||||
- text: 优先级队列应该在具有较低优先级的项之前返回具有较高优先级的项,否则以先进先出顺序返回项。
|
||||
testString: assert((function(){var test = new PriorityQueue(); test.enqueue(['A', 5]); test.enqueue(['B', 5]); test.enqueue(['C', 5]); test.enqueue(['D', 3]); test.enqueue(['E', 1]); test.enqueue(['F', 7]); var result = []; result.push(test.dequeue()); result.push(test.dequeue()); result.push(test.dequeue()); result.push(test.dequeue()); result.push(test.dequeue()); result.push(test.dequeue()); return result.join('') === 'EDABCF';}()));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`Queue`类应该有一个`enqueue`方法。
|
||||
|
||||
```js
|
||||
function PriorityQueue () {
|
||||
this.collection = [];
|
||||
this.printCollection = function() {
|
||||
console.log(this.collection);
|
||||
};
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new PriorityQueue();
|
||||
return typeof test.enqueue === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的`Queue`类应该有一个`dequeue`方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new PriorityQueue();
|
||||
return typeof test.dequeue === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
您的`Queue`类应该有一个`size`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new PriorityQueue();
|
||||
return typeof test.size === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
您的`Queue`类应该有一个`isEmpty`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new PriorityQueue();
|
||||
return typeof test.isEmpty === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
当项目入队和出列时,您的PriorityQueue应使用`size`方法正确跟踪当前项目数。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new PriorityQueue();
|
||||
test.enqueue(['David Brown', 2]);
|
||||
test.enqueue(['Jon Snow', 1]);
|
||||
var size1 = test.size();
|
||||
test.dequeue();
|
||||
var size2 = test.size();
|
||||
test.enqueue(['A', 3]);
|
||||
test.enqueue(['B', 3]);
|
||||
test.enqueue(['C', 3]);
|
||||
return size1 === 2 && size2 === 1 && test.size() === 4;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
当队列为空时, `isEmpty`方法应该返回`true` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new PriorityQueue();
|
||||
test.enqueue(['A', 1]);
|
||||
test.enqueue(['B', 1]);
|
||||
test.dequeue();
|
||||
var first = test.isEmpty();
|
||||
test.dequeue();
|
||||
return !first && test.isEmpty();
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
优先级队列应该在具有较低优先级的项之前返回具有较高优先级的项,否则以先进先出顺序返回项。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new PriorityQueue();
|
||||
test.enqueue(['A', 5]);
|
||||
test.enqueue(['B', 5]);
|
||||
test.enqueue(['C', 5]);
|
||||
test.enqueue(['D', 3]);
|
||||
test.enqueue(['E', 1]);
|
||||
test.enqueue(['F', 7]);
|
||||
var result = [];
|
||||
result.push(test.dequeue());
|
||||
result.push(test.dequeue());
|
||||
result.push(test.dequeue());
|
||||
result.push(test.dequeue());
|
||||
result.push(test.dequeue());
|
||||
result.push(test.dequeue());
|
||||
return result.join('') === 'EDABCF';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,74 +1,120 @@
|
||||
---
|
||||
id: 587d8250367417b2b2512c60
|
||||
title: 创建队列类
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建队列类
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">与堆栈一样,队列是元素的集合。但与堆栈不同,队列遵循FIFO(先入先出)原则。添加到队列的元素将被推送到队列的尾部或末尾,并且只允许删除队列前面的元素。我们可以使用数组来表示队列,但就像堆栈一样,我们希望限制我们对队列的控制量。队列类的两个主要方法是enqueue和dequeue方法。 enqueue方法将元素推送到队列的尾部,dequeue方法移除并返回队列前面的元素。其他有用的方法是front,size和isEmpty方法。说明编写一个将元素推送到队列尾部的入队方法,一个删除并返回前面元素的出列方法,一个让我们看到前面元素的前方法,一个显示长度的大小方法,以及一个isEmpty方法检查队列是否为空。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
与堆栈一样,队列是元素的集合。但与堆栈不同,队列遵循FIFO(先入先出)原则。添加到队列的元素将被推送到队列的尾部或末尾,并且只允许删除队列前面的元素。我们可以使用数组来表示队列,但就像堆栈一样,我们希望限制我们对队列的控制量。队列类的两个主要方法是enqueue和dequeue方法。 enqueue方法将元素推送到队列的尾部,dequeue方法移除并返回队列前面的元素。其他有用的方法是front,size和isEmpty方法。说明编写一个将元素推送到队列尾部的入队方法,一个删除并返回前面元素的出列方法,一个让我们看到前面元素的前方法,一个显示长度的大小方法,以及一个isEmpty方法检查队列是否为空。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>enqueue</code>方法。
|
||||
testString: assert((function(){var test = new Queue(); return (typeof test.enqueue === 'function')}()));
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>dequeue</code>方法。
|
||||
testString: assert((function(){var test = new Queue(); return (typeof test.dequeue === 'function')}()));
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>front</code>方法。
|
||||
testString: assert((function(){var test = new Queue(); return (typeof test.front === 'function')}()));
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>size</code>方法。
|
||||
testString: assert((function(){var test = new Queue(); return (typeof test.size === 'function')}()));
|
||||
- text: 您的<code>Queue</code>类应该有一个<code>isEmpty</code>方法。
|
||||
testString: assert((function(){var test = new Queue(); return (typeof test.isEmpty === 'function')}()));
|
||||
- text: <code>dequeue</code>方法应该删除并返回队列的前端元素
|
||||
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); test.enqueue('John'); return (test.dequeue() === 'Smith')}()));
|
||||
- text: <code>front</code>方法应该返回队列的front元素的值
|
||||
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); test.enqueue('John'); return (test.front() === 'Smith')}()));
|
||||
- text: <code>size</code>方法应该返回队列的长度
|
||||
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); return (test.size() === 1)}()));
|
||||
- text: 如果队列中有元素,则<code>isEmpty</code>方法应返回<code>false</code>
|
||||
testString: assert((function(){var test = new Queue(); test.enqueue('Smith'); return !(test.isEmpty())}()));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`Queue`类应该有一个`enqueue`方法。
|
||||
|
||||
```js
|
||||
function Queue () {
|
||||
var collection = [];
|
||||
this.print = function() {
|
||||
console.log(collection);
|
||||
};
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
return typeof test.enqueue === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的`Queue`类应该有一个`dequeue`方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
return typeof test.dequeue === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
您的`Queue`类应该有一个`front`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
return typeof test.front === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
您的`Queue`类应该有一个`size`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
return typeof test.size === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
您的`Queue`类应该有一个`isEmpty`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
return typeof test.isEmpty === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`dequeue`方法应该删除并返回队列的前端元素
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
test.enqueue('Smith');
|
||||
test.enqueue('John');
|
||||
return test.dequeue() === 'Smith';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`front`方法应该返回队列的front元素的值
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
test.enqueue('Smith');
|
||||
test.enqueue('John');
|
||||
return test.front() === 'Smith';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`size`方法应该返回队列的长度
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
test.enqueue('Smith');
|
||||
return test.size() === 1;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
如果队列中有元素,则`isEmpty`方法应返回`false`
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Queue();
|
||||
test.enqueue('Smith');
|
||||
return !test.isEmpty();
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,69 +1,83 @@
|
||||
---
|
||||
id: 8d1323c8c441eddfaeb5bdef
|
||||
title: 创建一个Set类
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建一个Set类
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在接下来的几个练习中,我们将创建一个函数来模拟一个名为“Set”的数据结构。 Set类似于数组,但不能包含重复值。 Set的典型用途是简单地检查项目是否存在。这可以用对象实现,例如: <blockquote> var set = new Object(); <br> set.foo = true; <br> //看看我们的集合中是否存在foo: <br> console.log(set.foo)// true </blockquote>在接下来的几个练习中,我们将从头开始构建一个全功能的Set。对于本练习,只要该值中尚不存在该值,就创建一个将值添加到set集合的函数。例如: <blockquote> this.add = function(element){ <br> //一些代码来为集合添加值<br> } </blockquote>如果成功添加该值,则该函数应返回<code>true</code>否则返回<code>false</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在接下来的几个练习中,我们将创建一个函数来模拟一个名为“Set”的数据结构。 Set类似于数组,但不能包含重复值。 Set的典型用途是简单地检查项目是否存在。这可以用对象实现,例如:
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> var set = new Object();
|
||||
> set.foo = true;
|
||||
> //看看我们的集合中是否存在foo:
|
||||
> console.log(set.foo)// true
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>Set</code>类应该有一个<code>add</code>方法。
|
||||
testString: 'assert((function(){var test = new Set(); return (typeof test.add === "function")}()), "Your <code>Set</code> class should have an <code>add</code> method.");'
|
||||
- text: 您的<code>add</code>方法不应添加重复值。
|
||||
testString: 'assert((function(){var test = new Set(); test.add("a"); test.add("b"); test.add("a"); var vals = test.values(); return (vals[0] === "a" && vals[1] === "b" && vals.length === 2)}()), "Your <code>add</code> method should not add duplicate values.");'
|
||||
- text: 成功添加值后, <code>add</code>方法应返回<code>true</code> 。
|
||||
testString: 'assert((function(){var test = new Set(); var result = test.add("a"); return (result != undefined) && (result === true);}()), "Your <code>add</code> method should return <code>true</code> when a value has been successfully added.");'
|
||||
- text: <code>add</code>重复值时, <code>add</code>方法应返回<code>false</code> 。
|
||||
testString: 'assert((function(){var test = new Set(); test.add("a"); var result = test.add("a"); return (result != undefined) && (result === false);}()), "Your <code>add</code> method should return <code>false</code> when a duplicate value is added.");'
|
||||
在接下来的几个练习中,我们将从头开始构建一个全功能的Set。对于本练习,只要该值中尚不存在该值,就创建一个将值添加到set集合的函数。例如:
|
||||
|
||||
```
|
||||
> this.add = function(element){
|
||||
> //一些代码来为集合添加值
|
||||
> }
|
||||
|
||||
</section>
|
||||
如果成功添加该值,则该函数应返回`true`否则返回`false` 。
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
# --hints--
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`Set`类应该有一个`add`方法。
|
||||
|
||||
```js
|
||||
function Set() {
|
||||
// the var collection will hold our set
|
||||
var collection = [];
|
||||
// this method will check for the presence of an element and return true or false
|
||||
this.has = function(element) {
|
||||
return (collection.indexOf(element) !== -1);
|
||||
};
|
||||
// this method will return all the values in the set
|
||||
this.values = function() {
|
||||
return collection;
|
||||
};
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
return typeof test.add === 'function';
|
||||
})(),
|
||||
'Your <code>Set</code> class should have an <code>add</code> method.'
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的`add`方法不应添加重复值。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
test.add('a');
|
||||
test.add('b');
|
||||
test.add('a');
|
||||
var vals = test.values();
|
||||
return vals[0] === 'a' && vals[1] === 'b' && vals.length === 2;
|
||||
})(),
|
||||
'Your <code>add</code> method should not add duplicate values.'
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
成功添加值后, `add`方法应返回`true` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
var result = test.add('a');
|
||||
return result != undefined && result === true;
|
||||
})(),
|
||||
'Your <code>add</code> method should return <code>true</code> when a value has been successfully added.'
|
||||
);
|
||||
```
|
||||
|
||||
`add`重复值时, `add`方法应返回`false` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
test.add('a');
|
||||
var result = test.add('a');
|
||||
return result != undefined && result === false;
|
||||
})(),
|
||||
'Your <code>add</code> method should return <code>false</code> when a duplicate value is added.'
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,74 +1,118 @@
|
||||
---
|
||||
id: 587d8250367417b2b2512c5f
|
||||
title: 创建一个堆栈类
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建一个堆栈类
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在上一节中,我们讨论了堆栈是什么以及如何使用数组来表示堆栈。在本节中,我们将创建自己的堆栈类。虽然您可以使用数组来创建堆栈,但有时最好限制我们对堆栈的控制量。除了<code>push</code>和<code>pop</code>方法之外,堆栈还有其他有用的方法。让我们为我们的堆栈类添加一个<code>peek</code> , <code>isEmpty</code>和<code>clear</code>方法。说明编写一个<code>push</code>方法,将元素推送到堆栈顶部,一个<code>pop</code>方法删除堆栈顶部的元素,一个<code>peek</code>堆栈中第一个元素的<code>peek</code>方法,一个<code>isEmpty</code>方法,用于检查是否存在stack是空的,是一个<code>clear</code>堆栈中所有元素的方法。通常堆栈没有这个,但我们添加了一个控制台记录集合的<code>print</code>助手方法。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在上一节中,我们讨论了堆栈是什么以及如何使用数组来表示堆栈。在本节中,我们将创建自己的堆栈类。虽然您可以使用数组来创建堆栈,但有时最好限制我们对堆栈的控制量。除了`push`和`pop`方法之外,堆栈还有其他有用的方法。让我们为我们的堆栈类添加一个`peek` , `isEmpty`和`clear`方法。说明编写一个`push`方法,将元素推送到堆栈顶部,一个`pop`方法删除堆栈顶部的元素,一个`peek`堆栈中第一个元素的`peek`方法,一个`isEmpty`方法,用于检查是否存在stack是空的,是一个`clear`堆栈中所有元素的方法。通常堆栈没有这个,但我们添加了一个控制台记录集合的`print`助手方法。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 你的<code>Stack</code>类应该有一个<code>push</code>方法。
|
||||
testString: assert((function(){var test = new Stack(); return (typeof test.push === 'function')}()));
|
||||
- text: 你的<code>Stack</code>类应该有一个<code>pop</code>方法。
|
||||
testString: assert((function(){var test = new Stack(); return (typeof test.pop === 'function')}()));
|
||||
- text: 你的<code>Stack</code>类应该有一个<code>peek</code>方法。
|
||||
testString: assert((function(){var test = new Stack(); return (typeof test.peek === 'function')}()));
|
||||
- text: 您的<code>Stack</code>类应该有一个<code>isEmpty</code>方法。
|
||||
testString: assert((function(){var test = new Stack(); return (typeof test.isEmpty === 'function')}()));
|
||||
- text: 你的<code>Stack</code>类应该有一个<code>clear</code>方法。
|
||||
testString: assert((function(){var test = new Stack(); return (typeof test.clear === 'function')}()));
|
||||
- text: <code>peek</code>方法应该返回堆栈的顶部元素
|
||||
testString: assert((function(){var test = new Stack(); test.push('CS50'); return (test.peek() === 'CS50')}()));
|
||||
- text: <code>pop</code>方法应该删除并返回堆栈的顶部元素
|
||||
testString: assert((function(){var test = new Stack(); test.push('CS50'); return (test.pop() === 'CS50');}()));
|
||||
- text: 如果堆栈不包含任何元素,则<code>isEmpty</code>方法应返回true
|
||||
testString: assert((function(){var test = new Stack(); return test.isEmpty()}()));
|
||||
- text: <code>clear</code>方法应该从堆栈中删除所有元素
|
||||
testString: assert((function(){var test = new Stack(); test.push('CS50'); test.clear(); return (test.isEmpty())}()));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
你的`Stack`类应该有一个`push`方法。
|
||||
|
||||
```js
|
||||
function Stack() {
|
||||
var collection = [];
|
||||
this.print = function() {
|
||||
console.log(collection);
|
||||
};
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
return typeof test.push === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
你的`Stack`类应该有一个`pop`方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
return typeof test.pop === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
你的`Stack`类应该有一个`peek`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
return typeof test.peek === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
您的`Stack`类应该有一个`isEmpty`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
return typeof test.isEmpty === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
你的`Stack`类应该有一个`clear`方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
return typeof test.clear === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`peek`方法应该返回堆栈的顶部元素
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
test.push('CS50');
|
||||
return test.peek() === 'CS50';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`pop`方法应该删除并返回堆栈的顶部元素
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
test.push('CS50');
|
||||
return test.pop() === 'CS50';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
如果堆栈不包含任何元素,则`isEmpty`方法应返回true
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
return test.isEmpty();
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`clear`方法应该从堆栈中删除所有元素
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Stack();
|
||||
test.push('CS50');
|
||||
test.clear();
|
||||
return test.isEmpty();
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,72 +1,120 @@
|
||||
---
|
||||
id: 587d8259367417b2b2512c84
|
||||
title: 创建Trie搜索树
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建Trie搜索树
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在这里,我们将继续从二叉搜索树开始,看看另一种称为trie的树结构。 trie是一种常用于保存字符串的有序搜索树,或者更通用的关联数组或其中键是字符串的动态数据集。当许多键具有重叠前缀时,它们非常擅长存储数据集,例如,字典中的所有单词。与二叉树不同,节点不与实际值相关联。相反,节点的路径表示特定的键。例如,如果我们想将字符串代码存储在trie中,我们将有四个节点,每个字母对应一个节点:c - o - d - e。然后,通过所有这些节点的路径将创建代码作为字符串 - 该路径是我们存储的密钥。然后,如果我们想要添加字符串编码,它将在d之后分支之前共享前三个代码节点。通过这种方式,可以非常紧凑地存储大型数据集。此外,搜索可以非常快,因为它实际上限于您存储的字符串的长度。此外,与二叉树不同,节点可以存储任意数量的子节点。正如您可能从上面的示例中猜到的那样,一些元数据通常存储在保存密钥结尾的节点上,以便在以后的遍历中仍可以检索密钥。例如,如果我们在上面的示例中添加了代码,我们需要某种方式来知道代码中的e代表先前输入的密钥的结尾。否则,当我们添加代码时,这些信息将会丢失。说明:让我们创建一个存储单词的trie。它将通过add方法接受单词并将它们存储在trie数据结构中。它还允许我们查询给定字符串是否是带有isWord方法的单词,并使用print方法检索输入到trie中的所有单词。 isWord应该返回一个布尔值,print应该将所有这些单词的数组作为字符串值返回。为了让我们验证这个数据结构是否正确实现,我们为树中的每个节点提供了一个Node结构。每个节点都是一个具有keys属性的对象,该属性是JavaScript Map对象。这将保存作为每个节点的有效密钥的各个字母。我们还在节点上创建了一个end属性,如果节点表示单词的终止,则可以将其设置为true。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在这里,我们将继续从二叉搜索树开始,看看另一种称为trie的树结构。 trie是一种常用于保存字符串的有序搜索树,或者更通用的关联数组或其中键是字符串的动态数据集。当许多键具有重叠前缀时,它们非常擅长存储数据集,例如,字典中的所有单词。与二叉树不同,节点不与实际值相关联。相反,节点的路径表示特定的键。例如,如果我们想将字符串代码存储在trie中,我们将有四个节点,每个字母对应一个节点:c - o - d - e。然后,通过所有这些节点的路径将创建代码作为字符串 - 该路径是我们存储的密钥。然后,如果我们想要添加字符串编码,它将在d之后分支之前共享前三个代码节点。通过这种方式,可以非常紧凑地存储大型数据集。此外,搜索可以非常快,因为它实际上限于您存储的字符串的长度。此外,与二叉树不同,节点可以存储任意数量的子节点。正如您可能从上面的示例中猜到的那样,一些元数据通常存储在保存密钥结尾的节点上,以便在以后的遍历中仍可以检索密钥。例如,如果我们在上面的示例中添加了代码,我们需要某种方式来知道代码中的e代表先前输入的密钥的结尾。否则,当我们添加代码时,这些信息将会丢失。说明:让我们创建一个存储单词的trie。它将通过add方法接受单词并将它们存储在trie数据结构中。它还允许我们查询给定字符串是否是带有isWord方法的单词,并使用print方法检索输入到trie中的所有单词。 isWord应该返回一个布尔值,print应该将所有这些单词的数组作为字符串值返回。为了让我们验证这个数据结构是否正确实现,我们为树中的每个节点提供了一个Node结构。每个节点都是一个具有keys属性的对象,该属性是JavaScript Map对象。这将保存作为每个节点的有效密钥的各个字母。我们还在节点上创建了一个end属性,如果节点表示单词的终止,则可以将其设置为true。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: Trie有一个add方法。
|
||||
testString: assert((function testTrie() { var test = false; if (typeof Trie !== 'undefined') { test = new Trie() } else { return false; }; return (typeof test.add == 'function') }()));
|
||||
- text: Trie有一种打印方法。
|
||||
testString: assert((function testTrie() { var test = false; if (typeof Trie !== 'undefined') { test = new Trie() } else { return false; }; return (typeof test.print == 'function') }()));
|
||||
- text: Trie有一个isWord方法。
|
||||
testString: assert((function testTrie() { var test = false; if (typeof Trie !== 'undefined') { test = new Trie() } else { return false; }; return (typeof test.isWord == 'function') }()));
|
||||
- text: print方法将添加到trie的所有项目作为数组中的字符串返回。
|
||||
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); }()));
|
||||
- text: isWord方法仅对添加到trie的单词返回true,对所有其他单词返回false。
|
||||
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')); }()));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
Trie有一个add方法。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
var Node = function() {
|
||||
this.keys = new Map();
|
||||
this.end = false;
|
||||
this.setEnd = function() {
|
||||
this.end = true;
|
||||
};
|
||||
this.isEnd = function() {
|
||||
return this.end;
|
||||
};
|
||||
};
|
||||
var Trie = function() {
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
assert(
|
||||
(function testTrie() {
|
||||
var test = false;
|
||||
if (typeof Trie !== 'undefined') {
|
||||
test = new Trie();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.add == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
Trie有一种打印方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function testTrie() {
|
||||
var test = false;
|
||||
if (typeof Trie !== 'undefined') {
|
||||
test = new Trie();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.print == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
Trie有一个isWord方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function testTrie() {
|
||||
var test = false;
|
||||
if (typeof Trie !== 'undefined') {
|
||||
test = new Trie();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.isWord == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
print方法将添加到trie的所有项目作为数组中的字符串返回。
|
||||
|
||||
```js
|
||||
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
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
isWord方法仅对添加到trie的单词返回true,对所有其他单词返回false。
|
||||
|
||||
```js
|
||||
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')
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,52 +1,27 @@
|
||||
---
|
||||
id: 587d825b367417b2b2512c8d
|
||||
title: 创建ES6 JavaScript地图
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 创建ES6 JavaScript地图
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">新版本的JavaScript为我们提供了一个内置的Map对象,它提供了我们在上一次挑战中手工编写的大部分功能。此Map对象虽然与常规JavaScript对象类似,但它提供了一些普通对象缺少的有用功能。例如,ES6 Map跟踪添加到其中的项目的插入顺序。以下是其方法的更完整概述: <code>.has(key)</code>基于键的存在返回true或false <code>.get(key)</code>返回与键相关联的值<code>.set(key, value)</code>设置新键,值对<code>.delete(key)</code>删除一个键,值对<code>.clear()</code>删除所有键值对<code>.entries()</code>以插入顺序返回所有键的数组<code>.values()</code>返回插入中所有值的数组order说明:定义一个JavaScript Map对象并为其分配一个名为myMap的变量。添加密钥,值对<code>freeCodeCamp</code> , <code>Awesome!</code>它。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
新版本的JavaScript为我们提供了一个内置的Map对象,它提供了我们在上一次挑战中手工编写的大部分功能。此Map对象虽然与常规JavaScript对象类似,但它提供了一些普通对象缺少的有用功能。例如,ES6 Map跟踪添加到其中的项目的插入顺序。以下是其方法的更完整概述: `.has(key)`基于键的存在返回true或false `.get(key)`返回与键相关联的值`.set(key, value)`设置新键,值对`.delete(key)`删除一个键,值对`.clear()`删除所有键值对`.entries()`以插入顺序返回所有键的数组`.values()`返回插入中所有值的数组order说明:定义一个JavaScript Map对象并为其分配一个名为myMap的变量。添加密钥,值对`freeCodeCamp` , `Awesome!`它。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: myMap对象存在。
|
||||
testString: assert(typeof myMap === 'object');
|
||||
- text: myMap包含键值对<code>freeCodeCamp</code> , <code>Awesome!</code> 。
|
||||
testString: assert(myMap.get('freeCodeCamp') === 'Awesome!');
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
myMap对象存在。
|
||||
|
||||
```js
|
||||
// change code below this line
|
||||
|
||||
assert(typeof myMap === 'object');
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
myMap包含键值对`freeCodeCamp` , `Awesome!` 。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(myMap.get('freeCodeCamp') === 'Awesome!');
|
||||
```
|
||||
|
||||
/section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,58 +1,46 @@
|
||||
---
|
||||
id: 587d8254367417b2b2512c70
|
||||
title: 在ES6中创建和添加集
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在ES6中创建和添加集
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">既然您已经完成了ES5,那么您将在ES6中执行类似的操作。这将相当容易。 ES6包含一个内置的数据结构<code>Set</code>现在包含了您手动编写的许多操作。我们来看看:创建一个新的空集: <code>var set = new Set();</code>您可以使用值创建一个集合: <code>var set = new Set(1);</code>您可以使用数组创建一个集合: <code>var set = new Set([1, 2, 3]);</code>创建集合后,可以使用<code>add</code>方法添加所需的值: <blockquote> var set = new Set([1,2,3]); <br> set.add([4,5,6]); </blockquote>提醒一下,集合是一种不能包含重复值的数据结构: <blockquote> var set = new Set([1,2,3,1,2,3]); <br> // set仅包含[1,2,3] </blockquote></section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">在本练习中,返回一个具有以下值的集合: <code>1, 2, 3, 'Taco', 'Cat', 'Awesome'</code> </section>
|
||||
既然您已经完成了ES5,那么您将在ES6中执行类似的操作。这将相当容易。 ES6包含一个内置的数据结构`Set`现在包含了您手动编写的许多操作。我们来看看:创建一个新的空集: `var set = new Set();`您可以使用值创建一个集合: `var set = new Set(1);`您可以使用数组创建一个集合: `var set = new Set([1, 2, 3]);`创建集合后,可以使用`add`方法添加所需的值:
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> var set = new Set(\[1,2,3]);
|
||||
> set.add(\[4,5,6]);
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: '您的<code>Set</code>应该只包含值<code>1, 2, 3, Taco, Cat, Awesome</code> 。'
|
||||
testString: 'assert((function(){var test = checkSet(); return (test.size == 6) && test.has(1) && test.has(2) && test.has(3) && test.has("Taco") && test.has("Cat") && test.has("Awesome");})());'
|
||||
提醒一下,集合是一种不能包含重复值的数据结构:
|
||||
|
||||
```
|
||||
> var set = new Set(\[1,2,3,1,2,3]);
|
||||
> // set仅包含\[1,2,3]
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
在本练习中,返回一个具有以下值的集合: `1, 2, 3, 'Taco', 'Cat', 'Awesome'`
|
||||
|
||||
<div id='js-seed'>
|
||||
# --hints--
|
||||
|
||||
您的`Set`应该只包含值`1, 2, 3, Taco, Cat, Awesome` 。
|
||||
|
||||
```js
|
||||
function checkSet() {
|
||||
var set = new Set([1, 2, 3, 3, 2, 1, 2, 3, 1]);
|
||||
// change code below this line
|
||||
|
||||
// change code above this line
|
||||
console.log(set);
|
||||
return set;
|
||||
}
|
||||
|
||||
checkSet();
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = checkSet();
|
||||
return (
|
||||
test.size == 6 &&
|
||||
test.has(1) &&
|
||||
test.has(2) &&
|
||||
test.has(3) &&
|
||||
test.has('Taco') &&
|
||||
test.has('Cat') &&
|
||||
test.has('Awesome')
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
# --solutions--
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
```js
|
||||
// solution required
|
||||
```
|
||||
|
||||
/section>
|
||||
|
@ -1,76 +1,113 @@
|
||||
---
|
||||
id: 587d8258367417b2b2512c80
|
||||
title: 删除二进制搜索树中的叶节点
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 删除二进制搜索树中的叶节点
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">这是我们将在二叉搜索树中实现更难操作的三个挑战中的第一个:删除。删除很困难,因为删除节点会破坏树中的链接。必须仔细重新建立这些链接以确保维护二叉树结构。对于某些删除,这意味着必须重新排列树。通常,在尝试删除节点时,您将遇到以下三种情况之一:叶节点:要删除的目标没有子节点。一个孩子:要删除的目标只有一个孩子。两个子节点:要删除的目标有两个子节点。删除叶节点很简单,我们只需删除它。删除具有一个子节点的节点也相对容易,我们只需删除它并将其父节点链接到我们删除的节点的子节点。但是,删除具有两个子节点的节点更加困难,因为这会创建两个需要重新连接到父树的子节点。我们将在第三个挑战中看到如何处理这个案例。此外,在处理删除时,您需要注意一些边缘情况。如果树是空的怎么办?如果要删除的节点是根节点怎么办?如果树中只有两个元素怎么办?现在,让我们处理第一种删除叶节点的情况。说明:在我们的二叉树上创建一个名为<code>remove</code> 。我们将在这里为我们的删除操作构建逻辑。首先,您需要在remove中创建一个函数,该函数在当前树中找到我们尝试删除的节点。如果树中不存在该节点,则<code>remove</code>应返回<code>null</code> 。现在,如果目标节点是没有子节点的叶节点,则应将其父节点引用设置为<code>null</code> 。这有效地从树中删除节点。为此,您必须跟踪我们尝试删除的节点的父节点。创建一种跟踪目标节点具有的子节点数的方法也很有用,因为这将确定我们的删除属于哪种情况。我们将在下一次挑战中处理第二和第三个案例。祝你好运! </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
这是我们将在二叉搜索树中实现更难操作的三个挑战中的第一个:删除。删除很困难,因为删除节点会破坏树中的链接。必须仔细重新建立这些链接以确保维护二叉树结构。对于某些删除,这意味着必须重新排列树。通常,在尝试删除节点时,您将遇到以下三种情况之一:叶节点:要删除的目标没有子节点。一个孩子:要删除的目标只有一个孩子。两个子节点:要删除的目标有两个子节点。删除叶节点很简单,我们只需删除它。删除具有一个子节点的节点也相对容易,我们只需删除它并将其父节点链接到我们删除的节点的子节点。但是,删除具有两个子节点的节点更加困难,因为这会创建两个需要重新连接到父树的子节点。我们将在第三个挑战中看到如何处理这个案例。此外,在处理删除时,您需要注意一些边缘情况。如果树是空的怎么办?如果要删除的节点是根节点怎么办?如果树中只有两个元素怎么办?现在,让我们处理第一种删除叶节点的情况。说明:在我们的二叉树上创建一个名为`remove` 。我们将在这里为我们的删除操作构建逻辑。首先,您需要在remove中创建一个函数,该函数在当前树中找到我们尝试删除的节点。如果树中不存在该节点,则`remove`应返回`null` 。现在,如果目标节点是没有子节点的叶节点,则应将其父节点引用设置为`null` 。这有效地从树中删除节点。为此,您必须跟踪我们尝试删除的节点的父节点。创建一种跟踪目标节点具有的子节点数的方法也很有用,因为这将确定我们的删除属于哪种情况。我们将在下一次挑战中处理第二和第三个案例。祝你好运!
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>remove</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.remove == 'function')})());
|
||||
- text: 尝试删除不存在的元素将返回<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; }; return (test.remove(100) == null); })());
|
||||
- text: 如果根节点没有子节点,则删除它会将根节点设置为<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); })());
|
||||
- text: <code>remove</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(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'); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// case 1: target has no children, change code below this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`remove`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.remove == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
尝试删除不存在的元素将返回`null` 。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.remove !== 'function') {
|
||||
return false;
|
||||
}
|
||||
return test.remove(100) == null;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
如果根节点没有子节点,则删除它会将根节点设置为`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`remove`方法从树中删除叶节点
|
||||
|
||||
```js
|
||||
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';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,121 +1,161 @@
|
||||
---
|
||||
id: 587d8258367417b2b2512c81
|
||||
title: 在二叉搜索树中删除具有一个子节点的节点
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在二叉搜索树中删除具有一个子节点的节点
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">现在我们可以删除叶子节点,让我们继续第二种情况:删除一个子节点。对于这种情况,假设我们有一棵树,其中包含以下节点1 - 2 - 3,其中1是根。要删除2,我们只需要在1到3中做出正确的引用。更一般地说,为了删除只有一个子节点的节点,我们将该节点的父引用作为树中的下一个节点。说明:我们在<code>remove</code>方法中提供了一些代码,用于完成上一次挑战中的任务。我们找到要删除的目标及其父节点,并定义目标节点具有的子节点数。让我们在这里为仅有一个子节点的目标节点添加下一个案例。在这里,我们必须确定单个子节点是树中的左或右分支,然后在父节点中设置正确的引用以指向此节点。另外,让我们考虑目标是根节点的情况(这意味着父节点将为<code>null</code> )。只要通过测试,请随意用自己的代码替换所有入门代码。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
现在我们可以删除叶子节点,让我们继续第二种情况:删除一个子节点。对于这种情况,假设我们有一棵树,其中包含以下节点1 - 2 - 3,其中1是根。要删除2,我们只需要在1到3中做出正确的引用。更一般地说,为了删除只有一个子节点的节点,我们将该节点的父引用作为树中的下一个节点。说明:我们在`remove`方法中提供了一些代码,用于完成上一次挑战中的任务。我们找到要删除的目标及其父节点,并定义目标节点具有的子节点数。让我们在这里为仅有一个子节点的目标节点添加下一个案例。在这里,我们必须确定单个子节点是树中的左或右分支,然后在父节点中设置正确的引用以指向此节点。另外,让我们考虑目标是根节点的情况(这意味着父节点将为`null` )。只要通过测试,请随意用自己的代码替换所有入门代码。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>remove</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.remove == 'function')})());
|
||||
- text: 尝试删除不存在的元素将返回<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; }; return (test.remove(100) == null); })());
|
||||
- text: 如果根节点没有子节点,则删除它会将根节点设置为<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); })());
|
||||
- text: <code>remove</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(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'); })());
|
||||
- text: <code>remove</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(-1); test.add(3); test.add(7); test.add(16); test.remove(16); test.remove(7); test.remove(3); return (test.inorder().join('') == '-1'); })());
|
||||
- text: 删除具有两个节点的树中的根将第二个节点设置为根。
|
||||
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'); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
this.remove = function(value) {
|
||||
if (this.root === null) {
|
||||
return null;
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
var target;
|
||||
var parent = null;
|
||||
// find the target value and its parent
|
||||
(function findValue(node = this.root) {
|
||||
if (value == node.value) {
|
||||
target = node;
|
||||
} else if (value < node.value && node.left !== null) {
|
||||
parent = node;
|
||||
return findValue(node.left);
|
||||
} else if (value < node.value && node.left === null) {
|
||||
return null;
|
||||
} else if (value > node.value && node.right !== null) {
|
||||
parent = node;
|
||||
return findValue(node.right);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}).bind(this)();
|
||||
if (target === null) {
|
||||
return null;
|
||||
}
|
||||
// count the children of the target to delete
|
||||
var children = (target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
|
||||
// case 1: target has no children
|
||||
if (children === 0) {
|
||||
if (target == this.root) {
|
||||
this.root = null;
|
||||
}
|
||||
else {
|
||||
if (parent.left == target) {
|
||||
parent.left = null;
|
||||
} else {
|
||||
parent.right = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// case 2: target has one child, change code below this line
|
||||
};
|
||||
}
|
||||
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`remove`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.remove == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
尝试删除不存在的元素将返回`null` 。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.remove !== 'function') {
|
||||
return false;
|
||||
}
|
||||
return test.remove(100) == null;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
如果根节点没有子节点,则删除它会将根节点设置为`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`remove`方法从树中删除叶节点
|
||||
|
||||
```js
|
||||
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';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`remove`方法删除具有一个子节点的节点。
|
||||
|
||||
```js
|
||||
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';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
删除具有两个节点的树中的根将第二个节点设置为根。
|
||||
|
||||
```js
|
||||
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';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,139 +1,234 @@
|
||||
---
|
||||
id: 587d8258367417b2b2512c82
|
||||
title: 在二叉搜索树中删除具有两个子节点的节点
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在二叉搜索树中删除具有两个子节点的节点
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">删除具有两个子节点的节点是最难实现的。删除这样的节点会生成两个不再连接到原始树结构的子树。我们如何重新连接它们?一种方法是在目标节点的右子树中找到最小值,并用该值替换目标节点。以这种方式选择替换确保它大于左子树中的每个节点,它成为新的父节点,但也小于右子树中的每个节点,它成为新的父节点。完成此替换后,必须从右子树中删除替换节点。即使这个操作也很棘手,因为替换可能是一个叶子,或者它本身可能是一个右子树的父亲。如果是叶子,我们必须删除其父对它的引用。否则,它必须是目标的正确子项。在这种情况下,我们必须用替换值替换目标值,并使目标引用替换的右子。说明:让我们通过处理第三种情况来完成我们的<code>remove</code>方法。我们为前两种情况再次提供了一些代码。现在添加一些代码来处理具有两个子节点的目标节点。任何边缘情况要注意?如果树只有三个节点怎么办?完成后,这将完成二进制搜索树的删除操作。干得好,这是一个非常难的问题! </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
删除具有两个子节点的节点是最难实现的。删除这样的节点会生成两个不再连接到原始树结构的子树。我们如何重新连接它们?一种方法是在目标节点的右子树中找到最小值,并用该值替换目标节点。以这种方式选择替换确保它大于左子树中的每个节点,它成为新的父节点,但也小于右子树中的每个节点,它成为新的父节点。完成此替换后,必须从右子树中删除替换节点。即使这个操作也很棘手,因为替换可能是一个叶子,或者它本身可能是一个右子树的父亲。如果是叶子,我们必须删除其父对它的引用。否则,它必须是目标的正确子项。在这种情况下,我们必须用替换值替换目标值,并使目标引用替换的右子。说明:让我们通过处理第三种情况来完成我们的`remove`方法。我们为前两种情况再次提供了一些代码。现在添加一些代码来处理具有两个子节点的目标节点。任何边缘情况要注意?如果树只有三个节点怎么办?完成后,这将完成二进制搜索树的删除操作。干得好,这是一个非常难的问题!
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>remove</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.remove == 'function')})());
|
||||
- text: 尝试删除不存在的元素将返回<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})());"
|
||||
- text: 如果根节点没有子节点,则删除它会将根节点设置为<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})());"
|
||||
- text: <code>remove</code>方法从树中删除叶节点
|
||||
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})());"
|
||||
- text: <code>remove</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(-1); test.add(3); test.add(7); test.add(16); test.remove(16); test.remove(7); test.remove(3); return (test.inorder().join('') == '-1'); })());
|
||||
- text: 删除具有两个节点的树中的根将第二个节点设置为根。
|
||||
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'); })());
|
||||
- text: <code>remove</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(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'); })());
|
||||
- text: 可以在三个节点的树上删除根。
|
||||
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); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
this.remove = function(value) {
|
||||
if (this.root === null) {
|
||||
return null;
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
var target;
|
||||
var parent = null;
|
||||
// find the target value and its parent
|
||||
(function findValue(node = this.root) {
|
||||
if (value == node.value) {
|
||||
target = node;
|
||||
} else if (value < node.value && node.left !== null) {
|
||||
parent = node;
|
||||
return findValue(node.left);
|
||||
} else if (value < node.value && node.left === null) {
|
||||
return null;
|
||||
} else if (value > node.value && node.right !== null) {
|
||||
parent = node;
|
||||
return findValue(node.right);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}).bind(this)();
|
||||
if (target === null) {
|
||||
return null;
|
||||
}
|
||||
// count the children of the target to delete
|
||||
var children = (target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
|
||||
// case 1: target has no children
|
||||
if (children === 0) {
|
||||
if (target == this.root) {
|
||||
this.root = null;
|
||||
}
|
||||
else {
|
||||
if (parent.left == target) {
|
||||
parent.left = null;
|
||||
} else {
|
||||
parent.right = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// case 2: target has one child
|
||||
else if (children == 1) {
|
||||
var newChild = (target.left !== null) ? target.left : target.right;
|
||||
if (parent === null) {
|
||||
target.value = newChild.value;
|
||||
target.left = null;
|
||||
target.right = null;
|
||||
} else if (newChild.value < parent.value) {
|
||||
parent.left = newChild;
|
||||
} else {
|
||||
parent.right = newChild;
|
||||
}
|
||||
target = null;
|
||||
}
|
||||
// case 3: target has two children, change code below this line
|
||||
};
|
||||
}
|
||||
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`remove`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.remove == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
尝试删除不存在的元素将返回`null` 。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
如果根节点没有子节点,则删除它会将根节点设置为`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`remove`方法从树中删除叶节点
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`remove`方法删除具有一个子节点的节点。
|
||||
|
||||
```js
|
||||
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';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
删除具有两个节点的树中的根将第二个节点设置为根。
|
||||
|
||||
```js
|
||||
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';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`remove`方法在保留二叉搜索树结构的同时删除具有两个子节点的节点。
|
||||
|
||||
```js
|
||||
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';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
可以在三个节点的树上删除根。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,73 +1,155 @@
|
||||
---
|
||||
id: 587d825d367417b2b2512c96
|
||||
title: 深度优先搜索
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 深度优先搜索
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">与<dfn>广度优先搜索</dfn>类似,这里我们将学习另一种称为<dfn>深度优先搜索的</dfn>图遍历算法。广度优先搜索搜索远离源节点的增量边长度,而<dfn>深度优先搜索</dfn>首先尽可能地沿着边缘路径向下<dfn>搜索</dfn> 。一旦到达路径的一端,搜索将回溯到具有未访问边缘路径的最后一个节点并继续搜索。在视觉上,这就是算法正在做的事情,其中顶部节点是搜索的起始点。 <img class="img-responsive" src="https://camo.githubusercontent.com/aaad9e39961daf34d967c616edeb50abf3bf1235/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f372f37662f44657074682d46697273742d5365617263682e676966">该算法的简单输出是可从给定节点到达的节点列表。因此,在实施此算法时,您需要跟踪您访问的节点。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">编写一个函数<code>dfs()</code> ,它将无向,邻接矩阵<code>graph</code>和节点标签<code>root</code>作为参数。节点标签将只是<code>0</code>和<code>n - 1</code>之间节点的数值,其中<code>n</code>是图中节点的总数。您的函数应输出从<code>root</code>可到达的所有节点的数组。 </section>
|
||||
与<dfn>广度优先搜索</dfn>类似,这里我们将学习另一种称为<dfn>深度优先搜索的</dfn>图遍历算法。广度优先搜索搜索远离源节点的增量边长度,而<dfn>深度优先搜索</dfn>首先尽可能地沿着边缘路径向下<dfn>搜索</dfn> 。一旦到达路径的一端,搜索将回溯到具有未访问边缘路径的最后一个节点并继续搜索。在视觉上,这就是算法正在做的事情,其中顶部节点是搜索的起始点。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
<img class='img-responsive' src='https://camo.githubusercontent.com/aaad9e39961daf34d967c616edeb50abf3bf1235/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f372f37662f44657074682d46697273742d5365617263682e676966'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>1</code>应返回一个数组<code>0</code> , <code>1</code> , <code>2</code> ,和<code>3</code> 。'
|
||||
testString: assert.sameMembers((function() { var graph = [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]; return dfs(graph, 1);})(), [0, 1, 2, 3]);
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>1</code>应该返回一个包含四个元素的数组。'
|
||||
testString: assert((function() { var graph = [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]; return dfs(graph, 1);})().length === 4);
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]</code> ,起始节点为<code>3</code>应该返回一个<code>3</code>的数组。'
|
||||
testString: assert.sameMembers((function() { var graph = [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]; return dfs(graph, 3);})(), [3]);
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]</code> ,起始节点为<code>3</code>应该返回一个包含一个元素的数组。'
|
||||
testString: assert((function() { var graph = [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]; return dfs(graph, 3);})().length === 1);
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>3</code>应该返回一个<code>2</code>和<code>3</code>的数组。'
|
||||
testString: assert.sameMembers((function() { var graph = [[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]; return dfs(graph, 3);})(), [2, 3]);
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>3</code>应该返回一个包含两个元素的数组。'
|
||||
testString: assert((function() { var graph = [[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]; return dfs(graph, 3);})().length === 2);
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>0</code>应该返回一个<code>0</code>和<code>1</code>的数组。'
|
||||
testString: assert.sameMembers((function() { var graph = [[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]; return dfs(graph, 0);})(), [0, 1]);
|
||||
- text: '输入图<code>[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]</code> ,起始节点为<code>0</code>应该返回一个包含两个元素的数组。'
|
||||
testString: assert((function() { var graph = [[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]; return dfs(graph, 0);})().length === 2);
|
||||
该算法的简单输出是可从给定节点到达的节点列表。因此,在实施此算法时,您需要跟踪您访问的节点。
|
||||
|
||||
```
|
||||
# --instructions--
|
||||
|
||||
</section>
|
||||
编写一个函数`dfs()` ,它将无向,邻接矩阵`graph`和节点标签`root`作为参数。节点标签将只是`0`和`n - 1`之间节点的数值,其中`n`是图中节点的总数。您的函数应输出从`root`可到达的所有节点的数组。
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
# --hints--
|
||||
|
||||
<div id='js-seed'>
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` ,起始节点为`1`应返回一个数组`0` , `1` , `2` ,和`3` 。
|
||||
|
||||
```js
|
||||
function dfs(graph, root) {
|
||||
|
||||
}
|
||||
|
||||
var exDFSGraph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
console.log(dfs(exDFSGraph, 3));
|
||||
|
||||
assert.sameMembers(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
return dfs(graph, 1);
|
||||
})(),
|
||||
[0, 1, 2, 3]
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` ,起始节点为`1`应该返回一个包含四个元素的数组。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
return dfs(graph, 1);
|
||||
})().length === 4
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` ,起始节点为`3`应该返回一个`3`的数组。
|
||||
|
||||
```js
|
||||
assert.sameMembers(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 0, 0]
|
||||
];
|
||||
return dfs(graph, 3);
|
||||
})(),
|
||||
[3]
|
||||
);
|
||||
```
|
||||
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` ,起始节点为`3`应该返回一个包含一个元素的数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 1, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 0, 0]
|
||||
];
|
||||
return dfs(graph, 3);
|
||||
})().length === 1
|
||||
);
|
||||
```
|
||||
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` ,起始节点为`3`应该返回一个`2`和`3`的数组。
|
||||
|
||||
```js
|
||||
assert.sameMembers(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[0, 0, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
return dfs(graph, 3);
|
||||
})(),
|
||||
[2, 3]
|
||||
);
|
||||
```
|
||||
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` ,起始节点为`3`应该返回一个包含两个元素的数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[0, 0, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
return dfs(graph, 3);
|
||||
})().length === 2
|
||||
);
|
||||
```
|
||||
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` ,起始节点为`0`应该返回一个`0`和`1`的数组。
|
||||
|
||||
```js
|
||||
assert.sameMembers(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[0, 0, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
return dfs(graph, 0);
|
||||
})(),
|
||||
[0, 1]
|
||||
);
|
||||
```
|
||||
|
||||
输入图`[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` ,起始节点为`0`应该返回一个包含两个元素的数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var graph = [
|
||||
[0, 1, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[0, 0, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
];
|
||||
return dfs(graph, 0);
|
||||
})().length === 2
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,82 +1,177 @@
|
||||
---
|
||||
id: 587d8257367417b2b2512c7d
|
||||
title: 找到二叉搜索树的最小和最大高度
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 找到二叉搜索树的最小和最大高度
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在最后一个挑战中,我们描述了树可能变得不平衡的情景。为了理解平衡的概念,让我们看看另一个树属性:高度。树中的高度表示从根节点到任何给定叶节点的距离。高度分支的树结构中的不同路径可以具有不同的高度,但是对于给定的树,将具有最小和最大高度。如果树是平衡的,则这些值最多相差一个。这意味着在平衡树中,所有叶节点都存在于同一级别中,或者如果它们不在同一级别内,则它们最多相隔一个级别。平衡的属性对于树很重要,因为它决定了树操作的效率。正如我们在上一次挑战中所解释的那样,我们面临严重不平衡树木的最坏情况时间复杂性。自平衡树通常用于在具有动态数据集的树中解决此问题。这些的常见例子包括AVL树,红黑树和B树。这些树都包含额外的内部逻辑,当插入或删除创建不平衡状态时,它会重新平衡树。注意:与height相似的属性是depth,它指的是给定节点距根节点的距离。说明:为我们的二叉树编写两种方法: <code>findMinHeight</code>和<code>findMaxHeight</code> 。这些方法应分别返回给定二叉树内最小和最大高度的整数值。如果节点为空,请为其指定高度<code>-1</code> (这是基本情况)。最后,添加第三个方法<code>isBalanced</code> ,它返回<code>true</code>或<code>false</code>具体取决于树是否平衡。您可以使用刚才编写的前两种方法来确定这一点。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在最后一个挑战中,我们描述了树可能变得不平衡的情景。为了理解平衡的概念,让我们看看另一个树属性:高度。树中的高度表示从根节点到任何给定叶节点的距离。高度分支的树结构中的不同路径可以具有不同的高度,但是对于给定的树,将具有最小和最大高度。如果树是平衡的,则这些值最多相差一个。这意味着在平衡树中,所有叶节点都存在于同一级别中,或者如果它们不在同一级别内,则它们最多相隔一个级别。平衡的属性对于树很重要,因为它决定了树操作的效率。正如我们在上一次挑战中所解释的那样,我们面临严重不平衡树木的最坏情况时间复杂性。自平衡树通常用于在具有动态数据集的树中解决此问题。这些的常见例子包括AVL树,红黑树和B树。这些树都包含额外的内部逻辑,当插入或删除创建不平衡状态时,它会重新平衡树。注意:与height相似的属性是depth,它指的是给定节点距根节点的距离。说明:为我们的二叉树编写两种方法: `findMinHeight`和`findMaxHeight` 。这些方法应分别返回给定二叉树内最小和最大高度的整数值。如果节点为空,请为其指定高度`-1` (这是基本情况)。最后,添加第三个方法`isBalanced` ,它返回`true`或`false`具体取决于树是否平衡。您可以使用刚才编写的前两种方法来确定这一点。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>findMinHeight</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.findMinHeight == 'function')})());
|
||||
- text: 二叉搜索树有一个名为<code>findMaxHeight</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.findMaxHeight == 'function')})());
|
||||
- text: 二叉搜索树有一个名为<code>isBalanced</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.isBalanced == 'function')})());
|
||||
- text: <code>findMinHeight</code>方法返回树的最小高度。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMinHeight !== '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.findMinHeight() == 1); })());
|
||||
- text: <code>findMaxHeight</code>方法返回树的最大高度。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMaxHeight !== '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.findMaxHeight() == 5); })());
|
||||
- text: 空树返回高度<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); })());
|
||||
- text: 如果树是平衡二叉搜索树,则<code>isBalanced</code>方法返回true。
|
||||
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(); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`findMinHeight`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.findMinHeight == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
二叉搜索树有一个名为`findMaxHeight`的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.findMaxHeight == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
二叉搜索树有一个名为`isBalanced`的方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.isBalanced == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`findMinHeight`方法返回树的最小高度。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.findMinHeight !== '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.findMinHeight() == 1;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`findMaxHeight`方法返回树的最大高度。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.findMaxHeight !== '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.findMaxHeight() == 5;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
空树返回高度`-1` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
如果树是平衡二叉搜索树,则`isBalanced`方法返回true。
|
||||
|
||||
```js
|
||||
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();
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,78 +1,139 @@
|
||||
---
|
||||
id: 587d8256367417b2b2512c7a
|
||||
title: 在二叉搜索树中查找最小值和最大值
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在二叉搜索树中查找最小值和最大值
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">这一系列挑战将介绍树数据结构。树木是计算机科学中重要且通用的数据结构。当然,他们的名字来源于这样一个事实:当他们看到它们时,它们看起来很像我们在自然界中熟悉的树木。树数据结构以一个节点(通常称为根)开始,并从此处分支到其他节点,每个节点可以具有更多子节点,依此类推。数据结构通常以顶部的根节点可视化;你可以把它想象成一棵倒置的天然树。首先,让我们描述一下我们将在树上遇到的一些常用术语。根节点是树的顶部。树中的数据点称为节点。具有通向其他节点的分支的节点被称为分支通向的节点的父节点(子节点)。其他更复杂的家庭术语适用于您所期望的。子树是指特定节点的所有后代,分支可以称为边,而叶节点是树末端没有子节点的节点。最后,请注意树本质上是递归数据结构。也就是说,节点的任何子节点都是其子树的父节点,依此类推。在为常见树操作设计算法时,树的递归性质非常重要。首先,我们将讨论一种特定类型的树,即二叉树。实际上,我们实际上将讨论一个特定的二叉树,一个二叉搜索树。让我们来描述这意味着什么。虽然树数据结构可以在单个节点上具有任意数量的分支,但是二叉树对于每个节点只能具有两个分支。此外,针对子子树排序二叉搜索树,使得左子树中的每个节点的值小于或等于父节点的值,并且右子树中的每个节点的值是大于或等于父节点的值。可视化这种关系以便更好地理解它是非常有帮助的: <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>现在这个有序的关系很容易看到。请注意,根节点8左侧的每个值都小于8,右侧的每个值都大于8.还要注意,此关系也适用于每个子树。例如,第一个左子项是子树。 3是父节点,它有两个子节点 - 通过控制二进制搜索树的规则,我们知道甚至没有看到这个节点的左子节点(及其任何子节点)将小于3,右边child(及其任何子级)将大于3(但也小于结构的根值),依此类推。二进制搜索树是非常常见且有用的数据结构,因为它们在几种常见操作(例如查找,插入和删除)的平均情况下提供对数时间。说明:我们将从简单开始。除了为树创建节点的函数之外,我们还在这里定义了二叉搜索树结构的骨架。观察每个节点可能具有左右值。如果它们存在,将为它们分配子子树。在我们的二叉搜索树中,定义两个方法, <code>findMin</code>和<code>findMax</code> 。这些方法应返回二叉搜索树中保存的最小值和最大值(不用担心现在向树中添加值,我们在后台添加了一些值)。如果遇到困难,请反思二进制搜索树必须为true的不变量:每个左子树小于或等于其父树,每个右子树大于或等于其父树。我们还要说我们的树只能存储整数值。如果树为空,则任一方法都应返回<code>null</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
这一系列挑战将介绍树数据结构。树木是计算机科学中重要且通用的数据结构。当然,他们的名字来源于这样一个事实:当他们看到它们时,它们看起来很像我们在自然界中熟悉的树木。树数据结构以一个节点(通常称为根)开始,并从此处分支到其他节点,每个节点可以具有更多子节点,依此类推。数据结构通常以顶部的根节点可视化;你可以把它想象成一棵倒置的天然树。首先,让我们描述一下我们将在树上遇到的一些常用术语。根节点是树的顶部。树中的数据点称为节点。具有通向其他节点的分支的节点被称为分支通向的节点的父节点(子节点)。其他更复杂的家庭术语适用于您所期望的。子树是指特定节点的所有后代,分支可以称为边,而叶节点是树末端没有子节点的节点。最后,请注意树本质上是递归数据结构。也就是说,节点的任何子节点都是其子树的父节点,依此类推。在为常见树操作设计算法时,树的递归性质非常重要。首先,我们将讨论一种特定类型的树,即二叉树。实际上,我们实际上将讨论一个特定的二叉树,一个二叉搜索树。让我们来描述这意味着什么。虽然树数据结构可以在单个节点上具有任意数量的分支,但是二叉树对于每个节点只能具有两个分支。此外,针对子子树排序二叉搜索树,使得左子树中的每个节点的值小于或等于父节点的值,并且右子树中的每个节点的值是大于或等于父节点的值。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
现在这个有序的关系很容易看到。请注意,根节点8左侧的每个值都小于8,右侧的每个值都大于8.还要注意,此关系也适用于每个子树。例如,第一个左子项是子树。 3是父节点,它有两个子节点 - 通过控制二进制搜索树的规则,我们知道甚至没有看到这个节点的左子节点(及其任何子节点)将小于3,右边child(及其任何子级)将大于3(但也小于结构的根值),依此类推。二进制搜索树是非常常见且有用的数据结构,因为它们在几种常见操作(例如查找,插入和删除)的平均情况下提供对数时间。说明:我们将从简单开始。除了为树创建节点的函数之外,我们还在这里定义了二叉搜索树结构的骨架。观察每个节点可能具有左右值。如果它们存在,将为它们分配子子树。在我们的二叉搜索树中,定义两个方法, `findMin`和`findMax` 。这些方法应返回二叉搜索树中保存的最小值和最大值(不用担心现在向树中添加值,我们在后台添加了一些值)。如果遇到困难,请反思二进制搜索树必须为true的不变量:每个左子树小于或等于其父树,每个右子树大于或等于其父树。我们还要说我们的树只能存储整数值。如果树为空,则任一方法都应返回`null` 。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>findMin</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.findMin == 'function')})());
|
||||
- text: 二叉搜索树有一个名为<code>findMax</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.findMax == 'function')})());
|
||||
- text: <code>findMin</code>方法返回二叉搜索树中的最小值。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.findMin !== '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.findMin() == 1; })());
|
||||
- text: <code>findMax</code>方法返回二叉搜索树中的最大值。
|
||||
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; })());
|
||||
- text: <code>findMin</code>和<code>findMax</code>方法为空树返回<code>null</code> 。
|
||||
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) })());
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`findMin`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.findMin == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
二叉搜索树有一个名为`findMax`的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.findMax == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
`findMin`方法返回二叉搜索树中的最小值。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.findMin !== '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.findMin() == 1;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`findMax`方法返回二叉搜索树中的最大值。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`findMin`和`findMax`方法为空树返回`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,74 +1,103 @@
|
||||
---
|
||||
id: 587d825b367417b2b2512c8c
|
||||
title: 用最小堆实现堆排序
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 用最小堆实现堆排序
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">现在我们可以添加和删除元素,让我们看看堆可用于的一些应用程序。堆通常用于实现优先级队列,因为它们始终将最大值或最小值的项存储在第一个位置。此外,它们还用于实现称为堆排序的排序算法。我们将在这里看到如何做到这一点。堆排序使用最小堆,与最大堆相反。最小堆始终将最小值的元素存储在根位置。堆排序通过获取未排序的数组,将数组中的每个项目添加到最小堆中,然后将最小堆中的每个项目提取到新数组中。最小堆结构确保新数组将包含至少最大顺序的原始项。这是最有效的排序算法之一,具有O(nlog(n))的平均和最差情况性能。说明:让我们用最小堆实现堆排序。您可以在此处调整最大堆代码。使用insert,remove和sort方法创建一个MinHeap对象。 sort方法应返回最小堆中从最小到最大排序的所有元素的数组。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
现在我们可以添加和删除元素,让我们看看堆可用于的一些应用程序。堆通常用于实现优先级队列,因为它们始终将最大值或最小值的项存储在第一个位置。此外,它们还用于实现称为堆排序的排序算法。我们将在这里看到如何做到这一点。堆排序使用最小堆,与最大堆相反。最小堆始终将最小值的元素存储在根位置。堆排序通过获取未排序的数组,将数组中的每个项目添加到最小堆中,然后将最小堆中的每个项目提取到新数组中。最小堆结构确保新数组将包含至少最大顺序的原始项。这是最有效的排序算法之一,具有O(nlog(n))的平均和最差情况性能。说明:让我们用最小堆实现堆排序。您可以在此处调整最大堆代码。使用insert,remove和sort方法创建一个MinHeap对象。 sort方法应返回最小堆中从最小到最大排序的所有元素的数组。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在MinHeap数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() }; return (typeof test == 'object')})());
|
||||
- text: MinHeap有一个名为insert的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() } else { return false; }; return (typeof test.insert == 'function')})());
|
||||
- text: MinHeap有一个名为remove的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() } else { return false; }; return (typeof test.remove == 'function')})());
|
||||
- text: MinHeap有一个名为sort的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MinHeap !== 'undefined') { test = new MinHeap() } else { return false; }; return (typeof test.sort == 'function')})());
|
||||
- text: sort方法返回一个数组,其中包含按排序顺序添加到最小堆的所有项。
|
||||
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)); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在MinHeap数据结构。
|
||||
|
||||
```js
|
||||
// check if array is sorted
|
||||
function isSorted(a){
|
||||
for(let i = 0; i < a.length - 1; i++)
|
||||
if(a[i] > a[i + 1])
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MinHeap !== 'undefined') {
|
||||
test = new MinHeap();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
MinHeap有一个名为insert的方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MinHeap !== 'undefined') {
|
||||
test = new MinHeap();
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// generate a randomly filled array
|
||||
var array = new Array();
|
||||
(function createArray(size = 5) {
|
||||
array.push(+(Math.random() * 100).toFixed(0));
|
||||
return (size > 1) ? createArray(size - 1) : undefined;
|
||||
})(25);
|
||||
var MinHeap = function() {
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
}
|
||||
return typeof test.insert == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
MinHeap有一个名为remove的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MinHeap !== 'undefined') {
|
||||
test = new MinHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.remove == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</section>
|
||||
MinHeap有一个名为sort的方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MinHeap !== 'undefined') {
|
||||
test = new MinHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.sort == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
sort方法返回一个数组,其中包含按排序顺序添加到最小堆的所有项。
|
||||
|
||||
```js
|
||||
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);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,59 +1,105 @@
|
||||
---
|
||||
id: 587d8256367417b2b2512c79
|
||||
title: 发生率矩阵
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 发生率矩阵
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">表示图形的另一种方式是将其置于<dfn>关联矩阵中。</dfn> <dfn>入射矩阵</dfn>是二维(2D)阵列。一般而言,关联矩阵在其两个维度之间涉及两个不同类别的对象。这种矩阵类似于邻接矩阵。但是,行和列在这里意味着其他东西。在图表中,我们有边缘和节点。这些将是我们的“两类不同的对象”。该矩阵将使行为节点,列为边。这意味着我们可以拥有不均匀的行数和列数。每列将代表一个独特的边缘。此外,每个边连接两个节点。要显示两个节点之间存在边缘,您将在特定列的两行中放置1。下面是一个3节点图,节点1和节点3之间有一条边。 <blockquote> 1 <br> --- <br> 1 | 1 <br> 2 | 0 <br> 3 | 1 </blockquote>以下是具有4个边和4个节点的<code>incidence matrix</code>的示例。请记住,列是边,行是节点本身。 <blockquote> 1 2 3 4 <br> -------- <br> 1 | 0 1 1 1 <br> 2 | 1 1 0 0 <br> 3 | 1 0 0 1 <br> 4 | 0 0 1 0 </blockquote>下面是同一件事的JavaScript实现。 <blockquote> var incMat = [ <br> [0,1,1,1], <br> [1,1,0,0], <br> [1,0,0,1], <br> [0,0,1,0] <br> ]。 </blockquote>要制作有向图,请使用<code>-1</code>表示离开特定节点的边,使用<code>1</code>作为边进入节点。 <blockquote> var incMatDirected = [ <br> [0,-1,1,-1], <br> [-1,1,0,0], <br> [1,0,0,1], <br> [0,0,-1,0] <br> ]。 </blockquote>图形的边缘也可以有权<dfn>重</dfn> 。到目前为止,我们有<dfn>未加权的</dfn>边缘,只有存在和缺少边是二进制( <code>0</code>或<code>1</code> )。根据您的应用,您可以拥有不同的重量。不同的权重表示为大于1的数字。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建具有五个节点和四个边的无向图的关联矩阵。该矩阵应该是多维数组。这五个节点在关系之后具有关系。第一边缘在第一和第二节点之间。第二个边缘位于第二个和第三个节点之间。第三个边缘位于第三个和第五个节点之间。并且四个边缘在第四和第二节点之间。所有边权重均为1,边缘顺序很重要。 </section>
|
||||
表示图形的另一种方式是将其置于<dfn>关联矩阵中。</dfn> <dfn>入射矩阵</dfn>是二维(2D)阵列。一般而言,关联矩阵在其两个维度之间涉及两个不同类别的对象。这种矩阵类似于邻接矩阵。但是,行和列在这里意味着其他东西。在图表中,我们有边缘和节点。这些将是我们的“两类不同的对象”。该矩阵将使行为节点,列为边。这意味着我们可以拥有不均匀的行数和列数。每列将代表一个独特的边缘。此外,每个边连接两个节点。要显示两个节点之间存在边缘,您将在特定列的两行中放置1。下面是一个3节点图,节点1和节点3之间有一条边。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> 1
|
||||
>
|
||||
> * * *
|
||||
>
|
||||
> 1 | 1
|
||||
> 2 | 0
|
||||
> 3 | 1
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>incMatUndirected</code>应该只包含五个节点。
|
||||
testString: assert((incMatUndirected.length === 5) && incMatUndirected.map(function(x) { return x.length === 4 }).reduce(function(a, b) { return a && b }) );
|
||||
- text: 第一个和第二个节点之间应该有第一条边。
|
||||
testString: assert((incMatUndirected[0][0] === 1) && (incMatUndirected[1][0] === 1));
|
||||
- text: 第二个和第三个节点之间应该有第二条边。
|
||||
testString: assert((incMatUndirected[1][1] === 1) && (incMatUndirected[2][1] === 1));
|
||||
- text: 第三个和第五个节点之间应该有第三条边。
|
||||
testString: assert((incMatUndirected[2][2] === 1) && (incMatUndirected[4][2] === 1));
|
||||
- text: 第二个和第四个节点之间应该有第四条边。
|
||||
testString: assert((incMatUndirected[1][3] === 1) && (incMatUndirected[3][3] === 1));
|
||||
以下是具有4个边和4个节点的`incidence matrix`的示例。请记住,列是边,行是节点本身。
|
||||
|
||||
```
|
||||
> 1 2 3 4
|
||||
>
|
||||
> * * *
|
||||
>
|
||||
> 1 | 0 1 1 1
|
||||
> 2 | 1 1 0 0
|
||||
> 3 | 1 0 0 1
|
||||
> 4 | 0 0 1 0
|
||||
|
||||
</section>
|
||||
下面是同一件事的JavaScript实现。
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
> var incMat = \[
|
||||
> \[0,1,1,1],
|
||||
> \[1,1,0,0],
|
||||
> \[1,0,0,1],
|
||||
> \[0,0,1,0]
|
||||
> ]。
|
||||
|
||||
<div id='js-seed'>
|
||||
要制作有向图,请使用`-1`表示离开特定节点的边,使用`1`作为边进入节点。
|
||||
|
||||
> var incMatDirected = \[
|
||||
> \[0,-1,1,-1],
|
||||
> \[-1,1,0,0],
|
||||
> \[1,0,0,1],
|
||||
> \[0,0,-1,0]
|
||||
> ]。
|
||||
|
||||
图形的边缘也可以有权
|
||||
|
||||
<dfn>重</dfn>
|
||||
|
||||
。到目前为止,我们有
|
||||
|
||||
<dfn>未加权的</dfn>
|
||||
|
||||
边缘,只有存在和缺少边是二进制( `0`或`1` )。根据您的应用,您可以拥有不同的重量。不同的权重表示为大于1的数字。
|
||||
|
||||
# --instructions--
|
||||
|
||||
创建具有五个节点和四个边的无向图的关联矩阵。该矩阵应该是多维数组。这五个节点在关系之后具有关系。第一边缘在第一和第二节点之间。第二个边缘位于第二个和第三个节点之间。第三个边缘位于第三个和第五个节点之间。并且四个边缘在第四和第二节点之间。所有边权重均为1,边缘顺序很重要。
|
||||
|
||||
# --hints--
|
||||
|
||||
`incMatUndirected`应该只包含五个节点。
|
||||
|
||||
```js
|
||||
var incMatUndirected = [
|
||||
|
||||
];
|
||||
|
||||
assert(
|
||||
incMatUndirected.length === 5 &&
|
||||
incMatUndirected
|
||||
.map(function (x) {
|
||||
return x.length === 4;
|
||||
})
|
||||
.reduce(function (a, b) {
|
||||
return a && b;
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
第一个和第二个节点之间应该有第一条边。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(incMatUndirected[0][0] === 1 && incMatUndirected[1][0] === 1);
|
||||
```
|
||||
|
||||
/section>
|
||||
第二个和第三个节点之间应该有第二条边。
|
||||
|
||||
```js
|
||||
assert(incMatUndirected[1][1] === 1 && incMatUndirected[2][1] === 1);
|
||||
```
|
||||
|
||||
第三个和第五个节点之间应该有第三条边。
|
||||
|
||||
```js
|
||||
assert(incMatUndirected[2][2] === 1 && incMatUndirected[4][2] === 1);
|
||||
```
|
||||
|
||||
第二个和第四个节点之间应该有第四条边。
|
||||
|
||||
```js
|
||||
assert(incMatUndirected[1][3] === 1 && incMatUndirected[3][3] === 1);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,59 +1,83 @@
|
||||
---
|
||||
id: 587d825a367417b2b2512c8a
|
||||
title: 将元素插入最大堆
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 将元素插入最大堆
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">现在我们将继续讨论另一个树数据结构,即二进制堆。二进制堆是部分有序的二叉树,它满足堆属性。 heap属性指定父节点和子节点之间的关系。您可能有一个最大堆,其中所有父节点都大于或等于其子节点,或者最小堆,其中反向为真。二进制堆也是完整的二叉树。这意味着树的所有级别都被完全填充,如果最后一级被部分填充,则从左到右填充。虽然二进制堆可以实现为具有包含左和右引用的节点的树结构,但是根据堆属性的部分排序允许我们用数组表示堆。父子关系是我们感兴趣的,通过简单的算术,我们可以计算任何父节点的子节点和任何子节点的父节点。例如,考虑二进制最小堆的数组表示: <code>[ 6, 22, 30, 37, 63, 48, 42, 76 ]</code>根节点是第一个元素,6。它的子节点是22和30.如果我们看在这些值的数组索引之间的关系中,对于索引i,子项为2 * i + 1和2 * i + 2.同样,索引0处的元素是索引1和2处的这两个子项的父项。通常,我们可以在任何索引处找到节点的父节点,其中包含以下内容:(i - 1)/ 2.当二叉树增长到任意大小时,这些模式将成立。最后,我们可以稍微调整一下,通过跳过数组中的第一个元素,使这个算法更容易。这样做会为给定索引i处的任何元素创建以下关系:示例数组表示形式: <code>[ null, 6, 22, 30, 37, 63, 48, 42, 76 ]</code>元素的左子项:i * 2元素的右子项:i * 2 + 1一个元素的父元素:i / 2一旦你绕过数学运算,使用数组表示非常有用,因为使用这个算法可以快速确定节点位置,因为你不需要内存使用量减少维护对子节点的引用。说明:这里我们将创建一个最大堆。首先创建一个insert方法,将元素添加到堆中。在插入期间,始终保持堆属性非常重要。对于最大堆,这意味着根元素应始终在树中具有最大值,并且所有父节点应该大于其子节点。对于堆的数组实现,这通常分三步完成:将新元素添加到数组的末尾。如果元素大于其父元素,请切换它们。继续切换,直到新元素小于其父元素或到达树的根。最后,添加一个print方法,该方法返回已添加到堆中的所有项的数组。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
现在我们将继续讨论另一个树数据结构,即二进制堆。二进制堆是部分有序的二叉树,它满足堆属性。 heap属性指定父节点和子节点之间的关系。您可能有一个最大堆,其中所有父节点都大于或等于其子节点,或者最小堆,其中反向为真。二进制堆也是完整的二叉树。这意味着树的所有级别都被完全填充,如果最后一级被部分填充,则从左到右填充。虽然二进制堆可以实现为具有包含左和右引用的节点的树结构,但是根据堆属性的部分排序允许我们用数组表示堆。父子关系是我们感兴趣的,通过简单的算术,我们可以计算任何父节点的子节点和任何子节点的父节点。例如,考虑二进制最小堆的数组表示: `[ 6, 22, 30, 37, 63, 48, 42, 76 ]`根节点是第一个元素,6。它的子节点是22和30.如果我们看在这些值的数组索引之间的关系中,对于索引i,子项为2 \* i + 1和2 \* i + 2.同样,索引0处的元素是索引1和2处的这两个子项的父项。通常,我们可以在任何索引处找到节点的父节点,其中包含以下内容:(i - 1)/ 2.当二叉树增长到任意大小时,这些模式将成立。最后,我们可以稍微调整一下,通过跳过数组中的第一个元素,使这个算法更容易。这样做会为给定索引i处的任何元素创建以下关系:示例数组表示形式: `[ null, 6, 22, 30, 37, 63, 48, 42, 76 ]`元素的左子项:i \* 2元素的右子项:i \* 2 + 1一个元素的父元素:i / 2一旦你绕过数学运算,使用数组表示非常有用,因为使用这个算法可以快速确定节点位置,因为你不需要内存使用量减少维护对子节点的引用。说明:这里我们将创建一个最大堆。首先创建一个insert方法,将元素添加到堆中。在插入期间,始终保持堆属性非常重要。对于最大堆,这意味着根元素应始终在树中具有最大值,并且所有父节点应该大于其子节点。对于堆的数组实现,这通常分三步完成:将新元素添加到数组的末尾。如果元素大于其父元素,请切换它们。继续切换,直到新元素小于其父元素或到达树的根。最后,添加一个print方法,该方法返回已添加到堆中的所有项的数组。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在MaxHeap数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() }; return (typeof test == 'object')})());
|
||||
- text: MaxHeap有一个名为insert的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() } else { return false; }; return (typeof test.insert == 'function')})());
|
||||
- text: MaxHeap有一个名为print的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() } else { return false; }; return (typeof test.print == 'function')})());
|
||||
- text: insert方法根据max heap属性添加元素。
|
||||
testString: 'assert((function() { var test = false; if (typeof MaxHeap !== ''undefined'') { test = new MaxHeap() } else { return false; }; test.insert(50); test.insert(100); test.insert(700); test.insert(32); test.insert(51); let result = test.print(); return ((result.length == 5) ? result[0] == 700 : result[1] == 700) })());'
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在MaxHeap数据结构。
|
||||
|
||||
```js
|
||||
var MaxHeap = function() {
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
MaxHeap有一个名为insert的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.insert == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
MaxHeap有一个名为print的方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.print == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
insert方法根据max heap属性添加元素。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
test.insert(50);
|
||||
test.insert(100);
|
||||
test.insert(700);
|
||||
test.insert(32);
|
||||
test.insert(51);
|
||||
let result = test.print();
|
||||
return result.length == 5 ? result[0] == 700 : result[1] == 700;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,74 +1,92 @@
|
||||
---
|
||||
id: 587d8259367417b2b2512c83
|
||||
title: 反转二叉树
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 反转二叉树
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">这里我们将创建一个反转二叉树的函数。给定二叉树,我们希望生成一个新树,它等效于该树的镜像。与原始树的inorder遍历相比,在倒置树上运行inorder遍历将以相反的顺序探索节点。在我们的二叉树上编写一个名为<code>invert</code>的方法。调用此方法应该反转当前树结构。理想情况下,我们希望在线性时间内就地执行此操作。也就是说,我们只访问每个节点一次,我们在不使用任何额外内存的情况下修改现有的树结构。祝你好运! </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
这里我们将创建一个反转二叉树的函数。给定二叉树,我们希望生成一个新树,它等效于该树的镜像。与原始树的inorder遍历相比,在倒置树上运行inorder遍历将以相反的顺序探索节点。在我们的二叉树上编写一个名为`invert`的方法。调用此方法应该反转当前树结构。理想情况下,我们希望在线性时间内就地执行此操作。也就是说,我们只访问每个节点一次,我们在不使用任何额外内存的情况下修改现有的树结构。祝你好运!
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>invert</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.invert == 'function')})());
|
||||
- text: <code>invert</code>方法正确地反转树结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.invert !== '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); test.invert(); return test.inorder().join('') == '877345348741'; })());
|
||||
- text: 反转空树返回<code>null</code> 。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.invert !== 'function') { return false; }; return (test.invert() == null); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`invert`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.invert == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`invert`方法正确地反转树结构。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.invert !== '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);
|
||||
test.invert();
|
||||
return test.inorder().join('') == '877345348741';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
反转空树返回`null` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.invert !== 'function') {
|
||||
return false;
|
||||
}
|
||||
return test.invert() == null;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,56 +1,48 @@
|
||||
---
|
||||
id: 587d8250367417b2b2512c5e
|
||||
title: 了解堆栈的工作原理
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 了解堆栈的工作原理
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">你可能熟悉桌子上的一摞书。您可能已使用文本编辑器的撤消功能。您也可能习惯按手机上的后退按钮返回应用中的上一个视图。你知道他们都有什么共同之处吗?它们都以某种方式存储数据,以便您可以向后遍历。堆栈中最顶层的书是最后放在那里的书。如果您从堆栈的顶部删除该书,则会显示在最后一本书之前放置的书籍,依此类推。如果你考虑一下,在上面的所有例子中,你都会获得<dfn>Last-In-First-Out</dfn>服务。我们将尝试使用我们的代码来模仿它。该数据存储方案称为<dfn>堆栈</dfn> 。特别是,我们必须实现将JavaScript对象推送到堆栈顶部的<code>push()</code>方法;和<code>pop()</code>方法,它删除当前位于堆栈顶部的JavaScript对象。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">这里我们有一堆作为数组表示的家庭作业: <code>"BIO12"</code>位于基础, <code>"PSY44"</code>位于堆栈的顶部。修改给定的数组,并使用上面提到的JavaScript方法将其视为<code>stack</code> 。从堆栈中删除顶部元素<code>"PSY44"</code> 。然后添加<code>"CS50"</code>作为堆栈的新顶部元素。 </section>
|
||||
你可能熟悉桌子上的一摞书。您可能已使用文本编辑器的撤消功能。您也可能习惯按手机上的后退按钮返回应用中的上一个视图。你知道他们都有什么共同之处吗?它们都以某种方式存储数据,以便您可以向后遍历。堆栈中最顶层的书是最后放在那里的书。如果您从堆栈的顶部删除该书,则会显示在最后一本书之前放置的书籍,依此类推。如果你考虑一下,在上面的所有例子中,你都会获得<dfn>Last-In-First-Out</dfn>服务。我们将尝试使用我们的代码来模仿它。该数据存储方案称为<dfn>堆栈</dfn> 。特别是,我们必须实现将JavaScript对象推送到堆栈顶部的`push()`方法;和`pop()`方法,它删除当前位于堆栈顶部的JavaScript对象。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>homeworkStack</code>应该只包含4个元素。
|
||||
testString: assert(homeworkStack.length === 4);
|
||||
- text: <code>homeworkStack</code>的最后一个元素应该是<code>"CS50"</code> 。
|
||||
testString: assert(homeworkStack[3] === 'CS50');
|
||||
- text: <code>homeworkStack</code>不应包含<code>"PSY44"</code> 。
|
||||
testString: assert(homeworkStack.indexOf('PSY44') === -1);
|
||||
- text: 不应更改<code>homeworkStack</code>的初始声明。
|
||||
testString: assert(code.match(/=/g).length === 1 && /homeworkStack\s*=\s*\["BIO12"\s*,\s*"HIS80"\s*,\s*"MAT122"\s*,\s*"PSY44"\]/.test(code));
|
||||
这里我们有一堆作为数组表示的家庭作业: `"BIO12"`位于基础, `"PSY44"`位于堆栈的顶部。修改给定的数组,并使用上面提到的JavaScript方法将其视为`stack` 。从堆栈中删除顶部元素`"PSY44"` 。然后添加`"CS50"`作为堆栈的新顶部元素。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`homeworkStack`应该只包含4个元素。
|
||||
|
||||
```js
|
||||
var homeworkStack = ["BIO12","HIS80","MAT122","PSY44"];
|
||||
// Only change code below this line
|
||||
|
||||
assert(homeworkStack.length === 4);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`homeworkStack`的最后一个元素应该是`"CS50"` 。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(homeworkStack[3] === 'CS50');
|
||||
```
|
||||
|
||||
/section>
|
||||
`homeworkStack`不应包含`"PSY44"` 。
|
||||
|
||||
```js
|
||||
assert(homeworkStack.indexOf('PSY44') === -1);
|
||||
```
|
||||
|
||||
不应更改`homeworkStack`的初始声明。
|
||||
|
||||
```js
|
||||
assert(
|
||||
code.match(/=/g).length === 1 &&
|
||||
/homeworkStack\s*=\s*\["BIO12"\s*,\s*"HIS80"\s*,\s*"MAT122"\s*,\s*"PSY44"\]/.test(
|
||||
code
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,110 +1,47 @@
|
||||
---
|
||||
id: 587d8254367417b2b2512c6e
|
||||
title: 对两组数据执行差异
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 对两组数据执行差异
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在本练习中,我们将对两组数据进行区分。我们将在我们的<code>Set</code>数据结构上创建一个名为<code>difference</code> 。集合的差异应比较两组并返回第一组中不存在的项目。此方法应将另一个<code>Set</code>作为参数,并返回两个集的<code>difference</code> 。例如,如果<code>setA = ['a','b','c']</code>和<code>setB = ['a','b','d','e']</code> ,则setA和setB的差异为: <code>setA.difference(setB) = ['c']</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在本练习中,我们将对两组数据进行区分。我们将在我们的`Set`数据结构上创建一个名为`difference` 。集合的差异应比较两组并返回第一组中不存在的项目。此方法应将另一个`Set`作为参数,并返回两个集的`difference` 。例如,如果`setA = ['a','b','c']`和`setB = ['a','b','d','e']` ,则setA和setB的差异为: `setA.difference(setB) = ['c']` 。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 你的<code>Set</code>类应该有一个<code>difference</code>方法。
|
||||
testString: assert((function(){var test = new Set(); return (typeof test.difference === 'function')})());
|
||||
- text: 收回了适当的收藏
|
||||
testString: assert((function(){var setA = new Set(); var setB = new Set(); setA.add('a'); setA.add('b'); setA.add('c'); setB.add('c'); setB.add('d'); var differenceSetAB = setA.difference(setB); return (differenceSetAB.size() === 2) && DeepEqual(differenceSetAB.values(), [ 'a', 'b' ])})());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
你的`Set`类应该有一个`difference`方法。
|
||||
|
||||
```js
|
||||
function Set() {
|
||||
// the var collection will hold the set
|
||||
var collection = [];
|
||||
// this method will check for the presence of an element and return true or false
|
||||
this.has = function(element) {
|
||||
return (collection.indexOf(element) !== -1);
|
||||
};
|
||||
// this method will return all the values in the set
|
||||
this.values = function() {
|
||||
return collection;
|
||||
};
|
||||
// this method will add an element to the set
|
||||
this.add = function(element) {
|
||||
if(!this.has(element)){
|
||||
collection.push(element);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will remove an element from a set
|
||||
this.remove = function(element) {
|
||||
if(this.has(element)){
|
||||
var index = collection.indexOf(element);
|
||||
collection.splice(index,1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will return the size of the collection
|
||||
this.size = function() {
|
||||
return collection.length;
|
||||
};
|
||||
// this method will return the union of two sets
|
||||
this.union = function(otherSet) {
|
||||
var unionSet = new Set();
|
||||
var firstSet = this.values();
|
||||
var secondSet = otherSet.values();
|
||||
firstSet.forEach(function(e){
|
||||
unionSet.add(e);
|
||||
});
|
||||
secondSet.forEach(function(e){
|
||||
unionSet.add(e);
|
||||
});
|
||||
return unionSet;
|
||||
};
|
||||
// this method will return the intersection of two sets as a new set
|
||||
this.intersection = function(otherSet) {
|
||||
var intersectionSet = new Set();
|
||||
var firstSet = this.values();
|
||||
firstSet.forEach(function(e){
|
||||
if(otherSet.has(e)){
|
||||
intersectionSet.add(e);
|
||||
}
|
||||
});
|
||||
return intersectionSet;
|
||||
};
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
return typeof test.difference === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
收回了适当的收藏
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
setA.add('a');
|
||||
setA.add('b');
|
||||
setA.add('c');
|
||||
setB.add('c');
|
||||
setB.add('d');
|
||||
var differenceSetAB = setA.difference(setB);
|
||||
return (
|
||||
differenceSetAB.size() === 2 &&
|
||||
DeepEqual(differenceSetAB.values(), ['a', 'b'])
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,129 +1,111 @@
|
||||
---
|
||||
id: 587d8254367417b2b2512c6f
|
||||
title: 对两组数据执行子集检查
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 对两组数据执行子集检查
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在本练习中,我们将对2组数据执行子集测试。我们将在我们的<code>Set</code>数据结构上创建一个名为<code>subset</code> 。这将比较第一组与第二组,如果第一组完全包含在第二组中,则它将返回true。例如,如果<code>setA = ['a','b']</code>和<code>setB = ['a','b','c','d']</code> ,则setA和setB的子集为: <code>setA.subset(setB)</code>应该是<code>true</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在本练习中,我们将对2组数据执行子集测试。我们将在我们的`Set`数据结构上创建一个名为`subset` 。这将比较第一组与第二组,如果第一组完全包含在第二组中,则它将返回true。例如,如果`setA = ['a','b']`和`setB = ['a','b','c','d']` ,则setA和setB的子集为: `setA.subset(setB)`应该是`true` 。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 你的<code>Set</code>类应该有一个<code>union</code>方法。
|
||||
testString: assert((function(){var test = new Set(); return (typeof test.subset === 'function')})());
|
||||
- text: 第一个Set()包含在第二个Set中
|
||||
testString: assert((function(){var setA = new Set(); var setB = new Set(); setA.add('a'); setB.add('b'); setB.add('c'); setB.add('a'); setB.add('d'); var subsetSetAB = setA.subset(setB);return (subsetSetAB === true)})());
|
||||
- text: '<code>["a", "b"].subset(["a", "b", "c", "d"])</code>应该返回<code>true</code> “)'
|
||||
testString: assert((function(){var setA = new Set(); var setB = new Set(); setA.add('a'); setA.add('b'); setB.add('a'); setB.add('b'); setB.add('c'); setB.add('d'); var subsetSetAB = setA.subset(setB); return (subsetSetAB === true)})());
|
||||
- text: '<code>["a", "b", "c"].subset(["a", "b"])</code>应返回<code>false</code> “)'
|
||||
testString: assert((function(){var setA = new Set(); var setB = new Set(); setA.add('a'); setA.add('b'); setA.add('c'); setB.add('a'); setB.add('b'); var subsetSetAB = setA.subset(setB); return (subsetSetAB === false)})());
|
||||
- text: '<code>[].subset([])</code>应该返回<code>true</code>'
|
||||
testString: assert((function(){var setA = new Set(); var setB = new Set(); var subsetSetAB = setA.subset(setB); return (subsetSetAB === true)})());
|
||||
- text: '<code>["a", "b"].subset(["c", "d"])</code>应返回<code>false</code> “)'
|
||||
testString: assert((function(){var setA = new Set(); var setB = new Set(); setA.add('a'); setA.add('b'); setB.add('c'); setB.add('d'); var subsetSetAB = setA.subset(setB); return (subsetSetAB === false)})());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
你的`Set`类应该有一个`union`方法。
|
||||
|
||||
```js
|
||||
function Set() {
|
||||
// the var collection will hold the set
|
||||
var collection = [];
|
||||
// this method will check for the presence of an element and return true or false
|
||||
this.has = function(element) {
|
||||
return (collection.indexOf(element) !== -1);
|
||||
};
|
||||
// this method will return all the values in the set
|
||||
this.values = function() {
|
||||
return collection;
|
||||
};
|
||||
// this method will add an element to the set
|
||||
this.add = function(element) {
|
||||
if(!this.has(element)){
|
||||
collection.push(element);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will remove an element from a set
|
||||
this.remove = function(element) {
|
||||
if(this.has(element)){
|
||||
var index = collection.indexOf(element);
|
||||
collection.splice(index,1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will return the size of the collection
|
||||
this.size = function() {
|
||||
return collection.length;
|
||||
};
|
||||
// this method will return the union of two sets
|
||||
this.union = function(otherSet) {
|
||||
var unionSet = new Set();
|
||||
var firstSet = this.values();
|
||||
var secondSet = otherSet.values();
|
||||
firstSet.forEach(function(e){
|
||||
unionSet.add(e);
|
||||
});
|
||||
secondSet.forEach(function(e){
|
||||
unionSet.add(e);
|
||||
});
|
||||
return unionSet;
|
||||
};
|
||||
// this method will return the intersection of two sets as a new set
|
||||
this.intersection = function(otherSet) {
|
||||
var intersectionSet = new Set();
|
||||
var firstSet = this.values();
|
||||
firstSet.forEach(function(e){
|
||||
if(otherSet.has(e)){
|
||||
intersectionSet.add(e);
|
||||
}
|
||||
});
|
||||
return intersectionSet;
|
||||
};
|
||||
// this method will return the difference of two sets as a new set
|
||||
this.difference = function(otherSet) {
|
||||
var differenceSet = new Set();
|
||||
var firstSet = this.values();
|
||||
firstSet.forEach(function(e){
|
||||
if(!otherSet.has(e)){
|
||||
differenceSet.add(e);
|
||||
}
|
||||
});
|
||||
return differenceSet;
|
||||
};
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
return typeof test.subset === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
第一个Set()包含在第二个Set中
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
setA.add('a');
|
||||
setB.add('b');
|
||||
setB.add('c');
|
||||
setB.add('a');
|
||||
setB.add('d');
|
||||
var subsetSetAB = setA.subset(setB);
|
||||
return subsetSetAB === true;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
`["a", "b"].subset(["a", "b", "c", "d"])`应该返回`true` “)
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
setA.add('a');
|
||||
setA.add('b');
|
||||
setB.add('a');
|
||||
setB.add('b');
|
||||
setB.add('c');
|
||||
setB.add('d');
|
||||
var subsetSetAB = setA.subset(setB);
|
||||
return subsetSetAB === true;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`["a", "b", "c"].subset(["a", "b"])`应返回`false` “)
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
setA.add('a');
|
||||
setA.add('b');
|
||||
setA.add('c');
|
||||
setB.add('a');
|
||||
setB.add('b');
|
||||
var subsetSetAB = setA.subset(setB);
|
||||
return subsetSetAB === false;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`[].subset([])`应该返回`true`
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
var subsetSetAB = setA.subset(setB);
|
||||
return subsetSetAB === true;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`["a", "b"].subset(["c", "d"])`应返回`false` “)
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
setA.add('a');
|
||||
setA.add('b');
|
||||
setB.add('c');
|
||||
setB.add('d');
|
||||
var subsetSetAB = setA.subset(setB);
|
||||
return subsetSetAB === false;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,87 +1,51 @@
|
||||
---
|
||||
id: 587d8253367417b2b2512c6c
|
||||
title: 在两个集上执行联合
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在两个集上执行联合
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在本练习中,我们将对两组数据执行联合。我们将在我们的<code>Set</code>数据结构上创建一个名为<code>union</code> 。此方法应将另一个<code>Set</code>作为参数,并返回两个集合的<code>union</code>集,不包括任何重复值。例如,如果<code>setA = ['a','b','c']</code>和<code>setB = ['a','b','d','e']</code> ,则setA和setB的并集为: <code>setA.union(setB) = ['a', 'b', 'c', 'd', 'e']</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在本练习中,我们将对两组数据执行联合。我们将在我们的`Set`数据结构上创建一个名为`union` 。此方法应将另一个`Set`作为参数,并返回两个集合的`union`集,不包括任何重复值。例如,如果`setA = ['a','b','c']`和`setB = ['a','b','d','e']` ,则setA和setB的并集为: `setA.union(setB) = ['a', 'b', 'c', 'd', 'e']` 。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 你的<code>Set</code>类应该有一个<code>union</code>方法。
|
||||
testString: assert((function(){var test = new Set(); return (typeof test.union === 'function')})());
|
||||
- text: 收回了适当的收藏
|
||||
testString: assert((function(){var setA = new Set(); var setB = new Set(); setA.add('a'); setA.add('b'); setA.add('c'); setB.add('c'); setB.add('d'); var unionSetAB = setA.union(setB); var final = unionSetAB.values(); return (final.indexOf('a') !== -1 && final.indexOf('b') !== -1 && final.indexOf('c') !== -1 && final.indexOf('d') !== -1 && final.length === 4)})());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
你的`Set`类应该有一个`union`方法。
|
||||
|
||||
```js
|
||||
function Set() {
|
||||
// the var collection will hold the set
|
||||
var collection = [];
|
||||
// this method will check for the presence of an element and return true or false
|
||||
this.has = function(element) {
|
||||
return (collection.indexOf(element) !== -1);
|
||||
};
|
||||
// this method will return all the values in the set
|
||||
this.values = function() {
|
||||
return collection;
|
||||
};
|
||||
// this method will add an element to the set
|
||||
this.add = function(element) {
|
||||
if(!this.has(element)){
|
||||
collection.push(element);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will remove an element from a set
|
||||
this.remove = function(element) {
|
||||
if(this.has(element)){
|
||||
var index = collection.indexOf(element);
|
||||
collection.splice(index,1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will return the size of the set
|
||||
this.size = function() {
|
||||
return collection.length;
|
||||
};
|
||||
// change code below this line
|
||||
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
return typeof test.union === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
收回了适当的收藏
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
setA.add('a');
|
||||
setA.add('b');
|
||||
setA.add('c');
|
||||
setB.add('c');
|
||||
setB.add('d');
|
||||
var unionSetAB = setA.union(setB);
|
||||
var final = unionSetAB.values();
|
||||
return (
|
||||
final.indexOf('a') !== -1 &&
|
||||
final.indexOf('b') !== -1 &&
|
||||
final.indexOf('c') !== -1 &&
|
||||
final.indexOf('d') !== -1 &&
|
||||
final.length === 4
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,99 +1,46 @@
|
||||
---
|
||||
id: 587d8253367417b2b2512c6d
|
||||
title: 在两组数据上执行交集
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在两组数据上执行交集
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在本练习中,我们将对两组数据执行交集。我们将在我们的<code>Set</code>数据结构上创建一个名为<code>intersection</code> 。集合的交集表示两个或更多集合共有的所有值。此方法应将另一个<code>Set</code>作为参数,并返回两个集合的<code>intersection</code> 。例如,如果<code>setA = ['a','b','c']</code>和<code>setB = ['a','b','d','e']</code> ,则setA和setB的交集为: <code>setA.intersection(setB) = ['a', 'b']</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
在本练习中,我们将对两组数据执行交集。我们将在我们的`Set`数据结构上创建一个名为`intersection` 。集合的交集表示两个或更多集合共有的所有值。此方法应将另一个`Set`作为参数,并返回两个集合的`intersection` 。例如,如果`setA = ['a','b','c']`和`setB = ['a','b','d','e']` ,则setA和setB的交集为: `setA.intersection(setB) = ['a', 'b']` 。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>Set</code>类应该有一个<code>intersection</code>方法。
|
||||
testString: assert((function(){var test = new Set(); return (typeof test.intersection === 'function')})());
|
||||
- text: 收回了适当的收藏
|
||||
testString: assert((function(){ var setA = new Set(); var setB = new Set(); setA.add('a'); setA.add('b'); setA.add('c'); setB.add('c'); setB.add('d'); var intersectionSetAB = setA.intersection(setB); return (intersectionSetAB.size() === 1 && intersectionSetAB.values()[0] === 'c')})());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`Set`类应该有一个`intersection`方法。
|
||||
|
||||
```js
|
||||
function Set() {
|
||||
// the var collection will hold the set
|
||||
var collection = [];
|
||||
// this method will check for the presence of an element and return true or false
|
||||
this.has = function(element) {
|
||||
return (collection.indexOf(element) !== -1);
|
||||
};
|
||||
// this method will return all the values in the set
|
||||
this.values = function() {
|
||||
return collection;
|
||||
};
|
||||
// this method will add an element to the set
|
||||
this.add = function(element) {
|
||||
if(!this.has(element)){
|
||||
collection.push(element);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will remove an element from a set
|
||||
this.remove = function(element) {
|
||||
if(this.has(element)){
|
||||
var index = collection.indexOf(element);
|
||||
collection.splice(index,1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// this method will return the size of the collection
|
||||
this.size = function() {
|
||||
return collection.length;
|
||||
};
|
||||
// this method will return the union of two sets
|
||||
this.union = function(otherSet) {
|
||||
var unionSet = new Set();
|
||||
var firstSet = this.values();
|
||||
var secondSet = otherSet.values();
|
||||
firstSet.forEach(function(e){
|
||||
unionSet.add(e);
|
||||
});
|
||||
secondSet.forEach(function(e){
|
||||
unionSet.add(e);
|
||||
});
|
||||
return unionSet;
|
||||
};
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new Set();
|
||||
return typeof test.intersection === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
收回了适当的收藏
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var setA = new Set();
|
||||
var setB = new Set();
|
||||
setA.add('a');
|
||||
setA.add('b');
|
||||
setA.add('c');
|
||||
setB.add('c');
|
||||
setB.add('d');
|
||||
var intersectionSetAB = setA.intersection(setB);
|
||||
return (
|
||||
intersectionSetAB.size() === 1 && intersectionSetAB.values()[0] === 'c'
|
||||
);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,61 +1,102 @@
|
||||
---
|
||||
id: 587d825b367417b2b2512c8b
|
||||
title: 从最大堆中删除元素
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 从最大堆中删除元素
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">现在我们可以向堆中添加元素,让我们看看如何删除元素。删除和插入元素都需要类似的逻辑。在最大堆中,您通常需要删除最大值,因此这只需要从树的根中提取它。这将破坏我们树的堆属性,因此我们必须以某种方式重新建立它。通常,对于最大堆,这可以通过以下方式完成:将堆中的最后一个元素移动到根位置。如果root的子节点大于它,则将root与较大值的子节点交换。继续交换,直到父级大于两个子级,或者到达树中的最后一级。说明:向我们的最大堆添加一个名为remove的方法。此方法应返回已添加到最大堆的最大值,并将其从堆中删除。它还应该重新排序堆,以便保持堆属性。删除元素后,堆中剩余的下一个最大元素应该成为根。此处再次添加插入方法。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
现在我们可以向堆中添加元素,让我们看看如何删除元素。删除和插入元素都需要类似的逻辑。在最大堆中,您通常需要删除最大值,因此这只需要从树的根中提取它。这将破坏我们树的堆属性,因此我们必须以某种方式重新建立它。通常,对于最大堆,这可以通过以下方式完成:将堆中的最后一个元素移动到根位置。如果root的子节点大于它,则将root与较大值的子节点交换。继续交换,直到父级大于两个子级,或者到达树中的最后一级。说明:向我们的最大堆添加一个名为remove的方法。此方法应返回已添加到最大堆的最大值,并将其从堆中删除。它还应该重新排序堆,以便保持堆属性。删除元素后,堆中剩余的下一个最大元素应该成为根。此处再次添加插入方法。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在MaxHeap数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() }; return (typeof test == 'object')})());
|
||||
- text: MaxHeap有一个名为print的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() } else { return false; }; return (typeof test.print == 'function')})());
|
||||
- text: MaxHeap有一个名为insert的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() } else { return false; }; return (typeof test.insert == 'function')})());
|
||||
- text: MaxHeap有一个名为remove的方法。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() } else { return false; }; return (typeof test.remove == 'function')})());
|
||||
- text: remove方法从最大堆中删除最大元素,同时保持最大堆属性。
|
||||
testString: assert((function() { var test = false; if (typeof MaxHeap !== 'undefined') { test = new MaxHeap() } else { return false; }; test.insert(30); test.insert(300); test.insert(500); test.insert(10); let result = []; result.push(test.remove()); result.push(test.remove()); result.push(test.remove()); result.push(test.remove()); return (result.join('') == '5003003010') })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在MaxHeap数据结构。
|
||||
|
||||
```js
|
||||
var MaxHeap = function() {
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
MaxHeap有一个名为print的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.print == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
MaxHeap有一个名为insert的方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.insert == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
MaxHeap有一个名为remove的方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.remove == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
remove方法从最大堆中删除最大元素,同时保持最大堆属性。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof MaxHeap !== 'undefined') {
|
||||
test = new MaxHeap();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
test.insert(30);
|
||||
test.insert(300);
|
||||
test.insert(500);
|
||||
test.insert(10);
|
||||
let result = [];
|
||||
result.push(test.remove());
|
||||
result.push(test.remove());
|
||||
result.push(test.remove());
|
||||
result.push(test.remove());
|
||||
return result.join('') == '5003003010';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,111 +1,92 @@
|
||||
---
|
||||
id: 587d8251367417b2b2512c65
|
||||
title: 按索引从链接列表中删除元素
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 按索引从链接列表中删除元素
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在我们继续讨论另一个数据结构之前,让我们先了解链接列表的最后几点练习。让我们编写一个<code>removeAt</code>方法,删除给定<code>index</code>处的<code>element</code> 。该方法应该称为<code>removeAt(index)</code> 。要删除某个<code>index</code>处的<code>element</code> ,我们需要在沿着链表移动时保持每个节点的运行计数。用于遍历链表的元素的常用技术涉及<dfn>“转轮”</dfn>或“哨兵”,它们“指向”代码所比较的节点。在我们的情况下,开始于<code>head</code>我们的名单中,我们先从一个<code>currentIndex</code>始于变量<code>0</code> 。对于我们传递的每个节点, <code>currentIndex</code>应该增加1。就像我们的<code>remove(element)</code>方法一样,当我们在removeAt(index)方法中删除节点时,我们需要注意不要孤立列表的其余部分。我们通过确保引用已删除节点的节点具有对下一节点的引用来保持节点连续。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">编写<code>removeAt(index)</code>方法,删除并返回给定<code>index</code>处的节点。如果给定<code>index</code>为负数,或者大于或等于链表<code>length</code> ,则该方法应返回<code>null</code> 。注意请记住保持<code>currentIndex</code>计数。 </section>
|
||||
在我们继续讨论另一个数据结构之前,让我们先了解链接列表的最后几点练习。让我们编写一个`removeAt`方法,删除给定`index`处的`element` 。该方法应该称为`removeAt(index)` 。要删除某个`index`处的`element` ,我们需要在沿着链表移动时保持每个节点的运行计数。用于遍历链表的元素的常用技术涉及<dfn>“转轮”</dfn>或“哨兵”,它们“指向”代码所比较的节点。在我们的情况下,开始于`head`我们的名单中,我们先从一个`currentIndex`始于变量`0` 。对于我们传递的每个节点, `currentIndex`应该增加1。就像我们的`remove(element)`方法一样,当我们在removeAt(index)方法中删除节点时,我们需要注意不要孤立列表的其余部分。我们通过确保引用已删除节点的节点具有对下一节点的引用来保持节点连续。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>LinkedList</code>类应该有一个<code>removeAt</code>方法。
|
||||
testString: 'assert((function(){var test = new LinkedList(); return (typeof test.removeAt === "function")}()), "Your <code>LinkedList</code> class should have a <code>removeAt</code> method.");'
|
||||
- text: 您的<code>removeAt</code>方法应该减少链表的<code>length</code>
|
||||
testString: 'assert((function(){var test = new LinkedList(); test.add("cat"); test.add("dog"); test.add("kitten"); test.removeAt(1); return test.size() === 2}()), "Your <code>removeAt</code> method should reduce the <code>length</code> of the linked list");'
|
||||
- text: 您的<code>removeAt</code>方法还应该返回已删除节点的元素。
|
||||
testString: 'assert((function(){var test = new LinkedList(); test.add("cat"); test.add("dog"); test.add("kitten"); return test.removeAt(1) === "dog"}()), "Your <code>removeAt</code> method should also return the element of the removed node.");'
|
||||
- text: 如果给定索引小于<code>0</code>则<code>removeAt</code>方法也应返回<code>null</code>
|
||||
testString: 'assert((function(){var test = new LinkedList(); test.add("cat"); test.add("dog"); test.add("kitten"); return (test.removeAt(-1) === null)}()), "Your <code>removeAt</code> method should also return <code>null</code> if the given index is less than <code>0</code>");'
|
||||
- text: 如果给定索引等于或大于链表的<code>length</code> ,则<code>removeAt</code>方法也应返回<code>null</code> 。
|
||||
testString: 'assert((function(){var test = new LinkedList(); test.add("cat"); test.add("dog"); test.add("kitten"); return (test.removeAt(3) === null)}()), "Your <code>removeAt</code> method should also return <code>null</code> if the given index is equal or more than the <code>length</code> of the linked list.");'
|
||||
编写`removeAt(index)`方法,删除并返回给定`index`处的节点。如果给定`index`为负数,或者大于或等于链表`length` ,则该方法应返回`null` 。注意请记住保持`currentIndex`计数。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`LinkedList`类应该有一个`removeAt`方法。
|
||||
|
||||
```js
|
||||
function LinkedList() {
|
||||
var length = 0;
|
||||
var head = null;
|
||||
|
||||
var Node = function(element){ // {1}
|
||||
this.element = element;
|
||||
this.next = null;
|
||||
};
|
||||
|
||||
this.size = function(){
|
||||
return length;
|
||||
};
|
||||
|
||||
this.head = function(){
|
||||
return head;
|
||||
};
|
||||
|
||||
this.add = function(element){
|
||||
var node = new Node(element);
|
||||
if(head === null){
|
||||
head = node;
|
||||
} else {
|
||||
var currentNode = head;
|
||||
|
||||
while(currentNode.next){
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
|
||||
currentNode.next = node;
|
||||
}
|
||||
|
||||
length++;
|
||||
};
|
||||
|
||||
this.remove = function(element){
|
||||
var currentNode = head;
|
||||
var previousNode;
|
||||
if(currentNode.element === element){
|
||||
head = currentNode.next;
|
||||
} else {
|
||||
while(currentNode.element !== element) {
|
||||
previousNode = currentNode;
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
|
||||
previousNode.next = currentNode.next;
|
||||
}
|
||||
|
||||
length --;
|
||||
};
|
||||
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
return typeof test.removeAt === 'function';
|
||||
})(),
|
||||
'Your <code>LinkedList</code> class should have a <code>removeAt</code> method.'
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的`removeAt`方法应该减少链表的`length`
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
test.removeAt(1);
|
||||
return test.size() === 2;
|
||||
})(),
|
||||
'Your <code>removeAt</code> method should reduce the <code>length</code> of the linked list'
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
您的`removeAt`方法还应该返回已删除节点的元素。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
return test.removeAt(1) === 'dog';
|
||||
})(),
|
||||
'Your <code>removeAt</code> method should also return the element of the removed node.'
|
||||
);
|
||||
```
|
||||
|
||||
如果给定索引小于`0`则`removeAt`方法也应返回`null`
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
return test.removeAt(-1) === null;
|
||||
})(),
|
||||
'Your <code>removeAt</code> method should also return <code>null</code> if the given index is less than <code>0</code>'
|
||||
);
|
||||
```
|
||||
|
||||
如果给定索引等于或大于链表的`length` ,则`removeAt`方法也应返回`null` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
return test.removeAt(3) === null;
|
||||
})(),
|
||||
'Your <code>removeAt</code> method should also return <code>null</code> if the given index is equal or more than the <code>length</code> of the linked list.'
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,94 +1,77 @@
|
||||
---
|
||||
id: 587d8251367417b2b2512c63
|
||||
title: 从链接列表中删除元素
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 从链接列表中删除元素
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">链接列表的任何实现所需的下一个重要方法是<code>remove</code>方法。此方法应将要删除的元素作为参数,然后搜索列表以查找并删除包含该元素的节点。每当我们从链表中删除一个节点时,重要的是我们不要意外地孤立列表的其余部分。回想一下,每个节点的<code>next</code>属性都指向列表中跟随它的节点。如果我们删除中间元素,比如说,我们要确保我们从该元素的前一个节点的<code>next</code>属性到中间元素的<code>next</code>属性(这是列表中的下一个节点)的连接!这可能听起来真的很混乱,所以让我们回到康加线的例子,这样我们就有了一个很好的概念模型。想象自己在康加舞线上,直接在你面前的人离开了这条线。刚离开生产线的人不再将手放在任何人身上 - 而且你不再把手放在离开的人身上。你向前走,把你的手放在你看到的下一个人身上。如果我们要删除的元素是<code>head</code>元素,我们将<code>head</code>重新分配给链表的第二个节点。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">编写一个<code>remove</code>方法,该方法接受一个元素并将其从链表中删除。注意每次从链接列表中删除元素时,列表的<code>length</code>应减少一。 </section>
|
||||
链接列表的任何实现所需的下一个重要方法是`remove`方法。此方法应将要删除的元素作为参数,然后搜索列表以查找并删除包含该元素的节点。每当我们从链表中删除一个节点时,重要的是我们不要意外地孤立列表的其余部分。回想一下,每个节点的`next`属性都指向列表中跟随它的节点。如果我们删除中间元素,比如说,我们要确保我们从该元素的前一个节点的`next`属性到中间元素的`next`属性(这是列表中的下一个节点)的连接!这可能听起来真的很混乱,所以让我们回到康加线的例子,这样我们就有了一个很好的概念模型。想象自己在康加舞线上,直接在你面前的人离开了这条线。刚离开生产线的人不再将手放在任何人身上 - 而且你不再把手放在离开的人身上。你向前走,把你的手放在你看到的下一个人身上。如果我们要删除的元素是`head`元素,我们将`head`重新分配给链表的第二个节点。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>LinkedList</code>类应该有一个<code>remove</code>方法。
|
||||
testString: 'assert((function(){var test = new LinkedList(); return (typeof test.remove === "function")}()), "Your <code>LinkedList</code> class should have a <code>remove</code> method.");'
|
||||
- text: <code>remove</code>第一个节点时, <code>remove</code>方法应重新分配<code>head</code>到第二个节点。
|
||||
testString: 'assert((function(){var test = new LinkedList(); test.add("cat"); test.add("dog"); test.remove("cat"); return test.head().element === "dog"}()), "Your <code>remove</code> method should reassign <code>head</code> to the second node when the first node is removed.");'
|
||||
- text: 对于每个删除的节点,您的<code>remove</code>方法应该将链表的<code>length</code>减少一个。
|
||||
testString: 'assert((function(){var test = new LinkedList(); test.add("cat"); test.add("dog"); test.remove("cat"); return test.size() === 1})(), "Your <code>remove</code> method should decrease the <code>length</code> of the linked list by one for every node removed.");'
|
||||
- text: 您的<code>remove</code>方法应该将已删除节点的上<code>next</code>节点的引用重新分配给已删除节点的<code>next</code>引用。
|
||||
testString: 'assert((function(){var test = new LinkedList(); test.add("cat"); test.add("dog");test.add("kitten"); test.remove("dog"); return test.head().next.element === "kitten"})(), "Your <code>remove</code> method should reassign the reference of the previous node of the removed node to the removed node's <code>next</code> reference.");'
|
||||
编写一个`remove`方法,该方法接受一个元素并将其从链表中删除。注意每次从链接列表中删除元素时,列表的`length`应减少一。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`LinkedList`类应该有一个`remove`方法。
|
||||
|
||||
```js
|
||||
function LinkedList() {
|
||||
var length = 0;
|
||||
var head = null;
|
||||
|
||||
var Node = function(element){
|
||||
this.element = element;
|
||||
this.next = null;
|
||||
};
|
||||
|
||||
this.size = function(){
|
||||
return length;
|
||||
};
|
||||
|
||||
this.head = function(){
|
||||
return head;
|
||||
};
|
||||
|
||||
this.add = function(element){
|
||||
var node = new Node(element);
|
||||
if(head === null){
|
||||
head = node;
|
||||
} else {
|
||||
var currentNode = head;
|
||||
|
||||
while(currentNode.next){
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
|
||||
currentNode.next = node;
|
||||
}
|
||||
|
||||
length++;
|
||||
};
|
||||
|
||||
this.remove = function(element){
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
};
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
return typeof test.remove === 'function';
|
||||
})(),
|
||||
'Your <code>LinkedList</code> class should have a <code>remove</code> method.'
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`remove`第一个节点时, `remove`方法应重新分配`head`到第二个节点。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.remove('cat');
|
||||
return test.head().element === 'dog';
|
||||
})(),
|
||||
'Your <code>remove</code> method should reassign <code>head</code> to the second node when the first node is removed.'
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
对于每个删除的节点,您的`remove`方法应该将链表的`length`减少一个。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.remove('cat');
|
||||
return test.size() === 1;
|
||||
})(),
|
||||
'Your <code>remove</code> method should decrease the <code>length</code> of the linked list by one for every node removed.'
|
||||
);
|
||||
```
|
||||
|
||||
您的`remove`方法应该将已删除节点的上`next`节点的引用重新分配给已删除节点的`next`引用。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
test.remove('dog');
|
||||
return test.head().next.element === 'kitten';
|
||||
})(),
|
||||
'Your <code>remove</code> method should reassign the reference of the previous node of the removed node to the removed node's <code>next</code> reference.'
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,55 +1,35 @@
|
||||
---
|
||||
id: 587d8254367417b2b2512c71
|
||||
title: 从ES6中的集中删除项目
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 从ES6中的集中删除项目
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">让我们使用<code>delete</code>方法练习从ES6集中<code>delete</code> 。首先,创建一个ES6 Set <code>var set = new Set([1,2,3]);</code>现在使用<code>delete</code>方法从Set中删除一个项目。 <blockquote> set.delete(1); <br> console.log([... set])//应该返回[2,3] <blockquote></blockquote></blockquote></section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">现在,创建一个整数为1,2,3,4和5的集合。删除值2和5,然后返回集合。 </section>
|
||||
让我们使用`delete`方法练习从ES6集中`delete` 。首先,创建一个ES6 Set `var set = new Set([1,2,3]);`现在使用`delete`方法从Set中删除一个项目。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> set.delete(1);
|
||||
> console.log(\[... set])//应该返回\[2,3]
|
||||
>
|
||||
> >
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: '您的集应包含值1,3和4'
|
||||
testString: assert((function(){var test = checkSet(); return test.has(1) && test.has(3) && test.has(4) && test.size === 3;})());
|
||||
# --instructions--
|
||||
|
||||
```
|
||||
现在,创建一个整数为1,2,3,4和5的集合。删除值2和5,然后返回集合。
|
||||
|
||||
</section>
|
||||
# --hints--
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的集应包含值1,3和4
|
||||
|
||||
```js
|
||||
function checkSet(){
|
||||
var set = //Create a set with values 1, 2, 3, 4, & 5
|
||||
//Remove the value 2
|
||||
//Remove the value 5
|
||||
//Return the set
|
||||
return set;
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = checkSet();
|
||||
return test.has(1) && test.has(3) && test.has(4) && test.size === 3;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
# --solutions--
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
```js
|
||||
// solution required
|
||||
```
|
||||
|
||||
/section>
|
||||
|
@ -1,78 +1,113 @@
|
||||
---
|
||||
id: 587d825a367417b2b2512c88
|
||||
title: 反转双重链接列表
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 反转双重链接列表
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">让我们为我们的双向链表创建一个名为reverse的方法,它可以反转列表。一旦执行该方法,头部应指向前一个尾部,尾部应指向前一个头部。现在,如果我们从头到尾遍历列表,我们应该以与原始列表相反的顺序来满足节点。尝试反转空列表应返回null。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
让我们为我们的双向链表创建一个名为reverse的方法,它可以反转列表。一旦执行该方法,头部应指向前一个尾部,尾部应指向前一个头部。现在,如果我们从头到尾遍历列表,我们应该以与原始列表相反的顺序来满足节点。尝试反转空列表应返回null。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在DoublyLinkedList数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; return (typeof test == 'object')})());
|
||||
- text: DoublyLinkedList有一个名为add的方法。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; if (test.add == undefined) { return false; }; return (typeof test.add == 'function')})());
|
||||
- text: DoublyLinkedList有一个名为reverse的方法。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; if (test.reverse == undefined) { return false; }; return (typeof test.reverse == 'function')})());
|
||||
- text: 反转空列表将返回null。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; return (test.reverse() == null); })());
|
||||
- text: 反向方法反转列表。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; test.add(58); test.add(61); test.add(32); test.reverse(); return (test.print().join('') == '326158'); })());
|
||||
- text: 当列表反转时,正确维护下一个和上一个引用。
|
||||
testString: assert((function() { var test = false; if (typeof DoublyLinkedList !== 'undefined') { test = new DoublyLinkedList() }; test.add(11); test.add(22); test.add(33); test.reverse(); return (test.printReverse().join('') == '112233'); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在DoublyLinkedList数据结构。
|
||||
|
||||
```js
|
||||
var Node = function(data, prev) {
|
||||
this.data = data;
|
||||
this.prev = prev;
|
||||
this.next = null;
|
||||
};
|
||||
var DoublyLinkedList = function() {
|
||||
this.head = null;
|
||||
this.tail = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
};
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
DoublyLinkedList有一个名为add的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
if (test.add == undefined) {
|
||||
return false;
|
||||
}
|
||||
return typeof test.add == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
DoublyLinkedList有一个名为reverse的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
if (test.reverse == undefined) {
|
||||
return false;
|
||||
}
|
||||
return typeof test.reverse == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
反转空列表将返回null。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
return test.reverse() == null;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
反向方法反转列表。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
test.add(58);
|
||||
test.add(61);
|
||||
test.add(32);
|
||||
test.reverse();
|
||||
return test.print().join('') == '326158';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
当列表反转时,正确维护下一个和上一个引用。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof DoublyLinkedList !== 'undefined') {
|
||||
test = new DoublyLinkedList();
|
||||
}
|
||||
test.add(11);
|
||||
test.add(22);
|
||||
test.add(33);
|
||||
test.reverse();
|
||||
return test.printReverse().join('') == '112233';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,111 +1,83 @@
|
||||
---
|
||||
id: 587d8251367417b2b2512c64
|
||||
title: 在链接列表中搜索
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在链接列表中搜索
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">让我们为链表类添加一些更有用的方法。如果我们可以判断我们的列表是否为空,那么它是否有用,就像我们的<code>Stack</code>和<code>Queue</code>类一样?我们还应该能够在链表中找到特定元素。遍历数据结构是你想要进行大量练习的东西!让我们创建一个<code>indexOf</code>方法,该方法将<code>element</code>作为参数,并在链表中返回该元素的<code>index</code> 。如果在链接列表中找不到该元素,则返回<code>-1</code> 。让我们实现一个相反的方法:一个<code>elementAt</code>方法,它将<code>index</code>作为参数并返回给定<code>index</code>处的<code>element</code> 。如果未找到任何<code>element</code> ,则返回<code>undefined</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">编写一个检查链表是否为空的<code>isEmpty</code>方法,返回给定元素<code>index</code>的<code>indexOf</code>方法,以及返回给定<code>index.</code>处<code>element</code>的<code>elementAt</code> <code>index.</code> </section>
|
||||
让我们为链表类添加一些更有用的方法。如果我们可以判断我们的列表是否为空,那么它是否有用,就像我们的`Stack`和`Queue`类一样?我们还应该能够在链表中找到特定元素。遍历数据结构是你想要进行大量练习的东西!让我们创建一个`indexOf`方法,该方法将`element`作为参数,并在链表中返回该元素的`index` 。如果在链接列表中找不到该元素,则返回`-1` 。让我们实现一个相反的方法:一个`elementAt`方法,它将`index`作为参数并返回给定`index`处的`element` 。如果未找到任何`element` ,则返回`undefined` 。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>LinkedList</code>类应该有一个<code>indexOf</code>方法。
|
||||
testString: assert((function(){var test = new LinkedList(); return (typeof test.indexOf === 'function')}()));
|
||||
- text: 您的<code>LinkedList</code>类应该有一个<code>elementAt</code>方法。
|
||||
testString: assert((function(){var test = new LinkedList(); return (typeof test.elementAt === 'function')}()));
|
||||
- text: 您的<code>size</code>方法应返回链表的长度
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); test.add('kitten'); return test.size() === 3}()));
|
||||
- text: <code>indexOf</code>方法应该返回给定元素的索引。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); test.add('kitten'); return test.indexOf('kitten') === 2}()));
|
||||
- text: 您的<code>elementAt</code>方法应该返回给定索引处的元素。
|
||||
testString: assert((function(){var test = new LinkedList(); test.add('cat'); test.add('dog'); test.add('kitten'); return test.elementAt(1) === 'dog'}()));
|
||||
编写一个检查链表是否为空的`isEmpty`方法,返回给定元素`index`的`indexOf`方法,以及返回给定`index.`处`element`的`elementAt` `index.`
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`LinkedList`类应该有一个`indexOf`方法。
|
||||
|
||||
```js
|
||||
function LinkedList() {
|
||||
var length = 0;
|
||||
var head = null;
|
||||
|
||||
var Node = function(element){ // {1}
|
||||
this.element = element;
|
||||
this.next = null;
|
||||
};
|
||||
|
||||
this.size = function() {
|
||||
return length;
|
||||
};
|
||||
|
||||
this.head = function(){
|
||||
return head;
|
||||
};
|
||||
|
||||
this.add = function(element){
|
||||
var node = new Node(element);
|
||||
if(head === null){
|
||||
head = node;
|
||||
} else {
|
||||
var currentNode = head;
|
||||
|
||||
while(currentNode.next){
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
|
||||
currentNode.next = node;
|
||||
}
|
||||
|
||||
length++;
|
||||
};
|
||||
|
||||
this.remove = function(element){
|
||||
var currentNode = head;
|
||||
var previousNode;
|
||||
if(currentNode.element === element){
|
||||
head = currentNode.next;
|
||||
} else {
|
||||
while(currentNode.element !== element) {
|
||||
previousNode = currentNode;
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
|
||||
previousNode.next = currentNode.next;
|
||||
}
|
||||
|
||||
length --;
|
||||
};
|
||||
|
||||
// Only change code below this line
|
||||
|
||||
// Only change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
return typeof test.indexOf === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的`LinkedList`类应该有一个`elementAt`方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
return typeof test.elementAt === 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
您的`size`方法应返回链表的长度
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
return test.size() === 3;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`indexOf`方法应该返回给定元素的索引。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
return test.indexOf('kitten') === 2;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
您的`elementAt`方法应该返回给定索引处的元素。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = new LinkedList();
|
||||
test.add('cat');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
return test.elementAt(1) === 'dog';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,54 +1,84 @@
|
||||
---
|
||||
id: 587d8253367417b2b2512c6a
|
||||
title: 键入的数组
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 键入的数组
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">数组是可以容纳许多不同元素的JavaScript对象。 <code>var complexArr = [1, 5, "2", "Word", {"name": "James"}];</code>基本上后台发生的事情是您的浏览器会自动为该阵列提供适当的内存空间。如果添加或删除数据,它也会根据需要进行更改。但是,在高性能和不同元素类型的世界中,有时您需要更具体地了解为阵列提供多少内存。 <dfn>类型化数组</dfn>是这个问题的答案。您现在可以说要为阵列提供多少内存。下面是可用的不同类型数组的基本概述,以及该数组中每个元素的大小(以字节为单位)。 <table class="table table-striped"><tbody><tr><th>类型</th><th>每个元素大小以字节为单位</th></tr><tr><td> <code>Int8Array</code> </td> <td> 1 </td></tr><tr><td> <code>Uint8Array</code> </td> <td> 1 </td></tr><tr><td> <code>Uint8ClampedArray</code> </td> <td> 1 </td></tr><tr><td> <code>Int16Array</code> </td> <td> 2 </td></tr><tr><td> <code>Uint16Array</code> </td> <td> 2 </td></tr><tr><td> <code>Int32Array</code> </td> <td> 4 </td></tr><tr><td> <code>Uint32Array</code> </td> <td> 4 </td></tr><tr><td> <code>Float32Array</code> </td> <td> 4 </td></tr><tr><td> <code>Float64Array</code> </td> <td> 8 </td></tr></tbody></table>创建这种类型的数组有两种方法。一种方法是直接创建它。下面是如何创建一个3长度的<code>Int16Array</code> 。 <blockquote> var i8 = new Int16Array(3); <br>的console.log(I8); <br> //返回[0,0,0] </blockquote>您还可以创建一个<dfn>缓冲区</dfn>来分配您希望数组占用多少数据(以字节为单位)。 <strong>注意</strong> <br>要使用缓冲区创建类型化数组,需要将字节数分配为上面列出的字节的倍数。 <blockquote> //以不同方式创建相同的Int16Array数组<br> var byteSize = 6; //需要是2的倍数<br> var buffer = new ArrayBuffer(byteSize); <br> var i8View = new Int16Array(buffer); <br> buffer.byteLength; //返回6 <br> i8View.byteLength; //返回6 <br>的console.log(i8View); //返回[0,0,0] </blockquote> <dfn>缓冲区</dfn>是仅承载数据的通用对象。您无法正常访问它们。要访问它们,您需要先创建一个<dfn>视图</dfn> 。 <blockquote> i8View [0] = 42; <br>的console.log(i8View); //返回[42,0,0] </blockquote> <strong>注意</strong> <br>类型化数组没有传统数组所具有的某些方法,如<code>.pop()</code>或<code>.push()</code> 。类型化数组也会失败<code>Array.isArray()</code> ,它会检查某些内容是否为数组。虽然更简单,但对于不太复杂的JavaScript引擎来说,这可能是一个优势。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">首先创建一个64字节的<code>buffer</code> 。然后创建一个<code>Int32Array</code>类型数组,其中包含一个名为<code>i32View</code>的视图。 </section>
|
||||
数组是可以容纳许多不同元素的JavaScript对象。 `var complexArr = [1, 5, "2", "Word", {"name": "James"}];`基本上后台发生的事情是您的浏览器会自动为该阵列提供适当的内存空间。如果添加或删除数据,它也会根据需要进行更改。但是,在高性能和不同元素类型的世界中,有时您需要更具体地了解为阵列提供多少内存。 <dfn>类型化数组</dfn>是这个问题的答案。您现在可以说要为阵列提供多少内存。下面是可用的不同类型数组的基本概述,以及该数组中每个元素的大小(以字节为单位)。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
| 类型 | 每个元素大小以字节为单位 |
|
||||
| ------------------- | ------------ |
|
||||
| `Int8Array` | 1 |
|
||||
| `Uint8Array` | 1 |
|
||||
| `Uint8ClampedArray` | 1 |
|
||||
| `Int16Array` | 2 |
|
||||
| `Uint16Array` | 2 |
|
||||
| `Int32Array` | 4 |
|
||||
| `Uint32Array` | 4 |
|
||||
| `Float32Array` | 4 |
|
||||
| `Float64Array` | 8 |
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>buffer</code>应该是64字节大。
|
||||
testString: assert(buffer.byteLength === 64);
|
||||
- text: 您的缓冲区的<code>i32View</code>视图应该是64字节大。
|
||||
testString: assert(i32View.byteLength === 64);
|
||||
- text: 您的缓冲区的<code>i32View</code>视图应为16个元素长。
|
||||
testString: assert(i32View.length === 16);
|
||||
创建这种类型的数组有两种方法。一种方法是直接创建它。下面是如何创建一个3长度的`Int16Array` 。
|
||||
|
||||
```
|
||||
> var i8 = new Int16Array(3);
|
||||
> 的console.log(I8);
|
||||
> //返回\[0,0,0]
|
||||
|
||||
</section>
|
||||
您还可以创建一个
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
<dfn>缓冲区</dfn>
|
||||
|
||||
<div id='js-seed'>
|
||||
来分配您希望数组占用多少数据(以字节为单位)。 **注意**
|
||||
要使用缓冲区创建类型化数组,需要将字节数分配为上面列出的字节的倍数。
|
||||
|
||||
> //以不同方式创建相同的Int16Array数组
|
||||
> var byteSize = 6; //需要是2的倍数
|
||||
> var buffer = new ArrayBuffer(byteSize);
|
||||
> var i8View = new Int16Array(buffer);
|
||||
> buffer.byteLength; //返回6
|
||||
> i8View.byteLength; //返回6
|
||||
> 的console.log(i8View); //返回\[0,0,0]
|
||||
|
||||
<dfn>缓冲区</dfn>
|
||||
|
||||
是仅承载数据的通用对象。您无法正常访问它们。要访问它们,您需要先创建一个
|
||||
|
||||
<dfn>视图</dfn>
|
||||
|
||||
。
|
||||
|
||||
> i8View \[0] = 42;
|
||||
> 的console.log(i8View); //返回\[42,0,0]
|
||||
|
||||
**注意**
|
||||
类型化数组没有传统数组所具有的某些方法,如`.pop()`或`.push()` 。类型化数组也会失败`Array.isArray()` ,它会检查某些内容是否为数组。虽然更简单,但对于不太复杂的JavaScript引擎来说,这可能是一个优势。
|
||||
|
||||
# --instructions--
|
||||
|
||||
首先创建一个64字节的`buffer` 。然后创建一个`Int32Array`类型数组,其中包含一个名为`i32View`的视图。
|
||||
|
||||
# --hints--
|
||||
|
||||
您的`buffer`应该是64字节大。
|
||||
|
||||
```js
|
||||
var buffer;
|
||||
var i32View;
|
||||
|
||||
assert(buffer.byteLength === 64);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的缓冲区的`i32View`视图应该是64字节大。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(i32View.byteLength === 64);
|
||||
```
|
||||
|
||||
/section>
|
||||
您的缓冲区的`i32View`视图应为16个元素长。
|
||||
|
||||
```js
|
||||
assert(i32View.length === 16);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,57 +1,30 @@
|
||||
---
|
||||
id: 587d8255367417b2b2512c72
|
||||
title: 在ES6集上使用.has和.size
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在ES6集上使用.has和.size
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">让我们看一下ES6 Set对象上可用的.has和.size方法。首先,创建一个ES6 Set <code>var set = new Set([1,2,3]);</code> .has方法将检查该值是否包含在集合中。 <code>var hasTwo = set.has(2);</code> .size方法将返回一个表示Set <code>var howBig = set.size;</code>大小的整数<code>var howBig = set.size;</code> </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">在本练习中,我们将数组和值传递给checkSet()函数。您的函数应该从数组参数创建ES6集。查找该集是否包含value参数。找到集合的大小。并在数组中返回这两个值。 </section>
|
||||
让我们看一下ES6 Set对象上可用的.has和.size方法。首先,创建一个ES6 Set `var set = new Set([1,2,3]);` .has方法将检查该值是否包含在集合中。 `var hasTwo = set.has(2);` .size方法将返回一个表示Set `var howBig = set.size;`大小的整数`var howBig = set.size;`
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: '<code>checkSet([4, 5, 6], 3)</code>应该返回[false,3]'
|
||||
testString: 'assert((function(){var test = checkSet([4,5,6], 3); return DeepEqual(test, [ false, 3 ]);})());'
|
||||
在本练习中,我们将数组和值传递给checkSet()函数。您的函数应该从数组参数创建ES6集。查找该集是否包含value参数。找到集合的大小。并在数组中返回这两个值。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`checkSet([4, 5, 6], 3)`应该返回[false,3]
|
||||
|
||||
```js
|
||||
function checkSet(arrToBeSet, checkValue){
|
||||
|
||||
// change code below this line
|
||||
|
||||
// change code above this line
|
||||
|
||||
}
|
||||
|
||||
checkSet([ 1, 2, 3], 2); // Should return [ true, 3 ]
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = checkSet([4, 5, 6], 3);
|
||||
return DeepEqual(test, [false, 3]);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
# --solutions--
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
```js
|
||||
// solution required
|
||||
```
|
||||
|
||||
/section>
|
||||
|
@ -1,80 +1,159 @@
|
||||
---
|
||||
id: 587d8258367417b2b2512c7f
|
||||
title: 在二叉搜索树中使用广度优先搜索
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在二叉搜索树中使用广度优先搜索
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">这里我们将介绍另一种树遍历方法:广度优先搜索。与上一次挑战中的深度优先搜索方法相比,广度优先搜索在继续进入下一级别之前探索树中给定级别中的所有节点。通常,队列在广度优先搜索算法的设计中用作辅助数据结构。在此方法中,我们首先将根节点添加到队列中。然后我们开始一个循环,我们将队列中的第一个项目出列,将其添加到一个新数组,然后检查它们的子子树。如果它的孩子不是空的,他们每个都被排队。此过程将继续,直到队列为空。说明:让我们在树中创建一个名为<code>levelOrder</code>的广度优先搜索方法。此方法应返回一个包含所有树节点值的数组,并以广度优先的方式进行探索。确保返回数组中的值,而不是节点本身。应从左到右遍历一个级别。接下来,让我们编写一个名为<code>reverseLevelOrder</code>的类似方法,它在每个级别执行相同的搜索,但是反向(从右到左)。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
这里我们将介绍另一种树遍历方法:广度优先搜索。与上一次挑战中的深度优先搜索方法相比,广度优先搜索在继续进入下一级别之前探索树中给定级别中的所有节点。通常,队列在广度优先搜索算法的设计中用作辅助数据结构。在此方法中,我们首先将根节点添加到队列中。然后我们开始一个循环,我们将队列中的第一个项目出列,将其添加到一个新数组,然后检查它们的子子树。如果它的孩子不是空的,他们每个都被排队。此过程将继续,直到队列为空。说明:让我们在树中创建一个名为`levelOrder`的广度优先搜索方法。此方法应返回一个包含所有树节点值的数组,并以广度优先的方式进行探索。确保返回数组中的值,而不是节点本身。应从左到右遍历一个级别。接下来,让我们编写一个名为`reverseLevelOrder`的类似方法,它在每个级别执行相同的搜索,但是反向(从右到左)。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>levelOrder</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.levelOrder == 'function')})());
|
||||
- text: 二叉搜索树有一个名为<code>reverseLevelOrder</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.reverseLevelOrder == 'function')})());
|
||||
- text: <code>levelOrder</code>方法返回按级别顺序探索的树节点值的数组。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.levelOrder !== 'function') { return false; }; test.add(7); test.add(1); test.add(9); test.add(0); test.add(3); test.add(8); test.add(10); test.add(2); test.add(5); test.add(4); test.add(6); return (test.levelOrder().join('') == '719038102546'); })());
|
||||
- text: <code>reverseLevelOrder</code>方法返回以反向级别顺序探索的树节点值的数组。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.reverseLevelOrder !== 'function') { return false; }; test.add(7); test.add(1); test.add(9); test.add(0); test.add(3); test.add(8); test.add(10); test.add(2); test.add(5); test.add(4); test.add(6); return (test.reverseLevelOrder().join('') == '791108305264'); })());
|
||||
- text: <code>levelOrder</code>方法为空树返回<code>null</code> 。
|
||||
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); })());
|
||||
- text: <code>reverseLevelOrder</code>方法为空树返回<code>null</code> 。
|
||||
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); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`levelOrder`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.levelOrder == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
二叉搜索树有一个名为`reverseLevelOrder`的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.reverseLevelOrder == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
`levelOrder`方法返回按级别顺序探索的树节点值的数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.levelOrder !== 'function') {
|
||||
return false;
|
||||
}
|
||||
test.add(7);
|
||||
test.add(1);
|
||||
test.add(9);
|
||||
test.add(0);
|
||||
test.add(3);
|
||||
test.add(8);
|
||||
test.add(10);
|
||||
test.add(2);
|
||||
test.add(5);
|
||||
test.add(4);
|
||||
test.add(6);
|
||||
return test.levelOrder().join('') == '719038102546';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`reverseLevelOrder`方法返回以反向级别顺序探索的树节点值的数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.reverseLevelOrder !== 'function') {
|
||||
return false;
|
||||
}
|
||||
test.add(7);
|
||||
test.add(1);
|
||||
test.add(9);
|
||||
test.add(0);
|
||||
test.add(3);
|
||||
test.add(8);
|
||||
test.add(10);
|
||||
test.add(2);
|
||||
test.add(5);
|
||||
test.add(4);
|
||||
test.add(6);
|
||||
return test.reverseLevelOrder().join('') == '791108305264';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`levelOrder`方法为空树返回`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`reverseLevelOrder`方法为空树返回`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,86 +1,224 @@
|
||||
---
|
||||
id: 587d8257367417b2b2512c7e
|
||||
title: 在二叉搜索树中使用深度优先搜索
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 在二叉搜索树中使用深度优先搜索
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">我们知道如何在二叉搜索树中搜索特定值。但是,如果我们只想探索整棵树呢?或者,如果我们没有有序树,我们只需要搜索一个值?这里我们将介绍一些可用于探索树数据结构的树遍历方法。首先是深度优先搜索。在深度优先搜索中,在搜索继续到另一个子树之前,尽可能深地探索给定子树。有三种方法可以完成:按顺序:从最左边的节点开始搜索,到最右边的节点结束。预购:在树叶前探索所有的根。下订单:在根之前探索所有的叶子。您可能会猜到,您可以选择不同的搜索方法,具体取决于树存储的数据类型以及您要查找的内容。对于二叉搜索树,inorder遍历以排序顺序返回节点。说明:这里我们将在二叉搜索树上创建这三种搜索方法。深度优先搜索是一种固有的递归操作,只要子节点存在,它就会继续探索更多的子树。一旦理解了这个基本概念,您就可以简单地重新排列探索节点和子树的顺序,以生成上述三个搜索中的任何一个。例如,在后序搜索中,我们希望在开始返回任何节点本身之前一直递归到叶节点,而在预订搜索中,我们希望首先返回节点,然后继续递归在树下。在我们的树上定义<code>inorder</code> , <code>preorder</code>和<code>postorder</code>方法。这些方法中的每一个都应该返回表示树遍历的项数组。确保返回数组中每个节点的整数值,而不是节点本身。最后,如果树为空,则返回<code>null</code> 。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">
|
||||
</section>
|
||||
我们知道如何在二叉搜索树中搜索特定值。但是,如果我们只想探索整棵树呢?或者,如果我们没有有序树,我们只需要搜索一个值?这里我们将介绍一些可用于探索树数据结构的树遍历方法。首先是深度优先搜索。在深度优先搜索中,在搜索继续到另一个子树之前,尽可能深地探索给定子树。有三种方法可以完成:按顺序:从最左边的节点开始搜索,到最右边的节点结束。预购:在树叶前探索所有的根。下订单:在根之前探索所有的叶子。您可能会猜到,您可以选择不同的搜索方法,具体取决于树存储的数据类型以及您要查找的内容。对于二叉搜索树,inorder遍历以排序顺序返回节点。说明:这里我们将在二叉搜索树上创建这三种搜索方法。深度优先搜索是一种固有的递归操作,只要子节点存在,它就会继续探索更多的子树。一旦理解了这个基本概念,您就可以简单地重新排列探索节点和子树的顺序,以生成上述三个搜索中的任何一个。例如,在后序搜索中,我们希望在开始返回任何节点本身之前一直递归到叶节点,而在预订搜索中,我们希望首先返回节点,然后继续递归在树下。在我们的树上定义`inorder` , `preorder`和`postorder`方法。这些方法中的每一个都应该返回表示树遍历的项数组。确保返回数组中每个节点的整数值,而不是节点本身。最后,如果树为空,则返回`null` 。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 存在<code>BinarySearchTree</code>数据结构。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() }; return (typeof test == 'object')})());
|
||||
- text: 二叉搜索树有一个名为<code>inorder</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.inorder == 'function')})());
|
||||
- text: 二叉搜索树有一个名为<code>preorder</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.preorder == 'function')})());
|
||||
- text: 二叉搜索树有一个名为<code>postorder</code>的方法。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; return (typeof test.postorder == 'function')})());
|
||||
- text: <code>inorder</code>方法返回由inorder遍历产生的节点值数组。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.inorder !== 'function') { return false; }; test.add(7); test.add(1); test.add(9); test.add(0); test.add(3); test.add(8); test.add(10); test.add(2); test.add(5); test.add(4); test.add(6); return (test.inorder().join('') == '012345678910'); })());
|
||||
- text: <code>preorder</code>方法返回由前序遍历产生的节点值数组。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.preorder !== 'function') { return false; }; test.add(7); test.add(1); test.add(9); test.add(0); test.add(3); test.add(8); test.add(10); test.add(2); test.add(5); test.add(4); test.add(6); return (test.preorder().join('') == '710325469810'); })());
|
||||
- text: <code>postorder</code>方法返回由后序遍历产生的节点值数组。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.postorder !== 'function') { return false; }; test.add(7); test.add(1); test.add(9); test.add(0); test.add(3); test.add(8); test.add(10); test.add(2); test.add(5); test.add(4); test.add(6); return (test.postorder().join('') == '024653181097'); })());
|
||||
- text: <code>inorder</code>方法为空树返回<code>null</code> 。
|
||||
testString: assert((function() { var test = false; if (typeof BinarySearchTree !== 'undefined') { test = new BinarySearchTree() } else { return false; }; if (typeof test.inorder !== 'function') { return false; }; return (test.inorder() == null); })());
|
||||
- text: <code>preorder</code>方法为空树返回<code>null</code> 。
|
||||
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); })());
|
||||
- text: <code>postorder</code>方法为空树返回<code>null</code> 。
|
||||
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); })());
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
存在`BinarySearchTree`数据结构。
|
||||
|
||||
```js
|
||||
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
|
||||
function Node(value) {
|
||||
this.value = value;
|
||||
this.left = null;
|
||||
this.right = null;
|
||||
}
|
||||
function BinarySearchTree() {
|
||||
this.root = null;
|
||||
// change code below this line
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
}
|
||||
return typeof test == 'object';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
二叉搜索树有一个名为`inorder`的方法。
|
||||
|
||||
```js
|
||||
console.info('after the test');
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.inorder == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
二叉搜索树有一个名为`preorder`的方法。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.preorder == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
/section>
|
||||
二叉搜索树有一个名为`postorder`的方法。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return typeof test.postorder == 'function';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`inorder`方法返回由inorder遍历产生的节点值数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.inorder !== 'function') {
|
||||
return false;
|
||||
}
|
||||
test.add(7);
|
||||
test.add(1);
|
||||
test.add(9);
|
||||
test.add(0);
|
||||
test.add(3);
|
||||
test.add(8);
|
||||
test.add(10);
|
||||
test.add(2);
|
||||
test.add(5);
|
||||
test.add(4);
|
||||
test.add(6);
|
||||
return test.inorder().join('') == '012345678910';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`preorder`方法返回由前序遍历产生的节点值数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.preorder !== 'function') {
|
||||
return false;
|
||||
}
|
||||
test.add(7);
|
||||
test.add(1);
|
||||
test.add(9);
|
||||
test.add(0);
|
||||
test.add(3);
|
||||
test.add(8);
|
||||
test.add(10);
|
||||
test.add(2);
|
||||
test.add(5);
|
||||
test.add(4);
|
||||
test.add(6);
|
||||
return test.preorder().join('') == '710325469810';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`postorder`方法返回由后序遍历产生的节点值数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.postorder !== 'function') {
|
||||
return false;
|
||||
}
|
||||
test.add(7);
|
||||
test.add(1);
|
||||
test.add(9);
|
||||
test.add(0);
|
||||
test.add(3);
|
||||
test.add(8);
|
||||
test.add(10);
|
||||
test.add(2);
|
||||
test.add(5);
|
||||
test.add(4);
|
||||
test.add(6);
|
||||
return test.postorder().join('') == '024653181097';
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`inorder`方法为空树返回`null` 。
|
||||
|
||||
```js
|
||||
assert(
|
||||
(function () {
|
||||
var test = false;
|
||||
if (typeof BinarySearchTree !== 'undefined') {
|
||||
test = new BinarySearchTree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (typeof test.inorder !== 'function') {
|
||||
return false;
|
||||
}
|
||||
return test.inorder() == null;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`preorder`方法为空树返回`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
`postorder`方法为空树返回`null` 。
|
||||
|
||||
```js
|
||||
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;
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,53 +1,34 @@
|
||||
---
|
||||
id: 587d8255367417b2b2512c73
|
||||
title: 使用Spread和Notes进行ES5 Set()集成
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 使用Spread和Notes进行ES5 Set()集成
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">你还记得ES6传播运营商<code>...</code> ? <code>...</code>可以在ES6中获取可迭代对象并将它们转换为数组。让我们创建一个Set,并检查传播函数。 <blockquote> var set = new Set([1,2,3]); <br> var setToArr = [... set] <br> console.log(setToArr)//返回[1,2,3] </blockquote></section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">在本练习中,我们将set对象传递给<code>checkSet</code>函数。它应该返回一个包含Set值的数组。现在你已经成功学会了如何使用ES6 <code>Set()</code>对象,干得好! </section>
|
||||
你还记得ES6传播运营商`...` ? `...`可以在ES6中获取可迭代对象并将它们转换为数组。让我们创建一个Set,并检查传播函数。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
> var set = new Set(\[1,2,3]);
|
||||
> var setToArr = \[... set]
|
||||
> console.log(setToArr)//返回\[1,2,3]
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的套装已正确退回!
|
||||
testString: 'assert((function(){var test = checkSet(new Set([1,2,3,4,5,6,7])); return DeepEqual(test, [ 1, 2, 3, 4, 5, 6, 7 ]);})());'
|
||||
# --instructions--
|
||||
|
||||
```
|
||||
在本练习中,我们将set对象传递给`checkSet`函数。它应该返回一个包含Set值的数组。现在你已经成功学会了如何使用ES6 `Set()`对象,干得好!
|
||||
|
||||
</section>
|
||||
# --hints--
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的套装已正确退回!
|
||||
|
||||
```js
|
||||
function checkSet(set){
|
||||
// change code below this line
|
||||
|
||||
// change code above this line
|
||||
}
|
||||
|
||||
assert(
|
||||
(function () {
|
||||
var test = checkSet(new Set([1, 2, 3, 4, 5, 6, 7]));
|
||||
return DeepEqual(test, [1, 2, 3, 4, 5, 6, 7]);
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
# --solutions--
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
```js
|
||||
// solution required
|
||||
```
|
||||
|
||||
/section>
|
||||
|
@ -1,62 +1,31 @@
|
||||
---
|
||||
id: 587d8251367417b2b2512c61
|
||||
title: 使用链接列表中的节点
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
title: 使用链接列表中的节点
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">您将在计算机科学中遇到的另一个常见数据结构是<dfn>链表</dfn> 。链表是数据元素的线性集合,称为“节点”,每个数据元素指向下一个。链表中的每个<dfn>节点都</dfn>包含两个关键信息: <code>element</code>本身和对下一个<code>node</code>的引用。想象一下你在康加舞线上。你的手掌握在线下的下一个人身上,你身后的人就会抓住你。你可以直接看到这个人,但是他们阻挡了前方其他人的视线。一个节点就像一个康加舞线上的人:他们知道自己是谁,他们只能看到下一个人,但他们并不知道前方或后方的其他人。 </section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">在我们的代码编辑器中,我们创建了两个节点, <code>Kitten</code>和<code>Puppy</code> ,我们手动将<code>Kitten</code>节点连接到<code>Puppy</code>节点。创建<code>Cat</code>和<code>Dog</code>节点并手动将它们添加到该行。 </section>
|
||||
您将在计算机科学中遇到的另一个常见数据结构是<dfn>链表</dfn> 。链表是数据元素的线性集合,称为“节点”,每个数据元素指向下一个。链表中的每个<dfn>节点都</dfn>包含两个关键信息: `element`本身和对下一个`node`的引用。想象一下你在康加舞线上。你的手掌握在线下的下一个人身上,你身后的人就会抓住你。你可以直接看到这个人,但是他们阻挡了前方其他人的视线。一个节点就像一个康加舞线上的人:他们知道自己是谁,他们只能看到下一个人,但他们并不知道前方或后方的其他人。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的<code>Puppy</code>节点应该具有对<code>Cat</code>节点的引用。
|
||||
testString: assert(Puppy.next.element === "Cat");
|
||||
- text: 您的<code>Cat</code>节点应该具有对<code>Dog</code>节点的引用。
|
||||
testString: assert(Cat.next.element === "Dog");
|
||||
在我们的代码编辑器中,我们创建了两个节点, `Kitten`和`Puppy` ,我们手动将`Kitten`节点连接到`Puppy`节点。创建`Cat`和`Dog`节点并手动将它们添加到该行。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
您的`Puppy`节点应该具有对`Cat`节点的引用。
|
||||
|
||||
```js
|
||||
var Node = function(element){
|
||||
this.element = element;
|
||||
this.next = null;
|
||||
};
|
||||
var Kitten = new Node("Kitten");
|
||||
var Puppy = new Node("Puppy");
|
||||
|
||||
Kitten.next = Puppy;
|
||||
// only add code below this line
|
||||
|
||||
// test your code
|
||||
console.log(Kitten.next);
|
||||
|
||||
assert(Puppy.next.element === 'Cat');
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
您的`Cat`节点应该具有对`Dog`节点的引用。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
assert(Cat.next.element === 'Dog');
|
||||
```
|
||||
|
||||
/section>
|
||||
# --solutions--
|
||||
|
||||
|
Reference in New Issue
Block a user