Merge branch 'krahets:master' into typescript

This commit is contained in:
Daniel 2022-12-23 09:32:32 +11:00 committed by GitHub
commit ae0abb6d0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 333 additions and 87 deletions

View File

@ -1,6 +1,4 @@
> Tip: If this PR is not related to the coding or code translation, please ignore the checklist.
### Checklist
If this PR is related to coding or code translation, please fill out the checklist.
- [ ] I've tested the code and ensured the outputs are the same as the outputs of reference codes.
- [ ] I've checked the codes (formatting, comments, indentation, file header, etc) carefully.

View File

@ -36,7 +36,7 @@
- 开源免费,所有同学都可在网上获取本书;
- 新手友好,适合算法初学者自主学习入门;
- 动画讲解,尽可能地保证平滑的学习曲线;
- 代码导向,提供精简、可运行的算法代码;
- 代码导向,提供可一键运行的算法代码;
- 讨论学习,提问一般能在三日内得到回复;
如果感觉本书对你有所帮助,请点个 Star :star: 支持一下,谢谢!

View File

@ -0,0 +1,53 @@
/**
* File: binary_search.js
* Created Time: 2022-12-22
* Author: JoseHung (szhong@link.cuhk.edu.hk)
*/
/* 二分查找(双闭区间) */
function binarySearch(nums, target) {
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
let i = 0, j = nums.length - 1;
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while (i <= j) {
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
j = m - 1;
else
return m; // 找到目标元素,返回其索引
}
// 未找到目标元素,返回 -1
return -1;
}
/* 二分查找(左闭右开) */
function binarySearch1(nums, target) {
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
let i = 0, j = nums.length;
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while (i < j) {
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
j = m;
else // 找到目标元素,返回其索引
return m;
}
// 未找到目标元素,返回 -1
return -1;
}
/* Driver Code */
var target = 6;
var nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92];
/* 二分查找(双闭区间) */
var index = binarySearch(nums, target);
console.log("目标元素 6 的索引 = " + index);
/* 二分查找(左闭右开) */
index = binarySearch1(nums, target);
console.log("目标元素 6 的索引 = " + index);

View File

@ -0,0 +1,48 @@
/**
* File: linear-search.js
* Created Time: 2022-12-22
* Author: JoseHung (szhong@link.cuhk.edu.hk)
*/
const ListNode = require("../include/ListNode");
/* 线性查找(数组) */
function linearSearchArray(nums, target) {
// 遍历数组
for (let i = 0; i < nums.length; i++) {
// 找到目标元素,返回其索引
if (nums[i] === target) {
return i;
}
}
// 未找到目标元素,返回 -1
return -1;
}
/* 线性查找(链表)*/
function linearSearchLinkedList(head, target) {
// 遍历链表
while(head) {
// 找到目标结点,返回之
if(head.val === target) {
return head;
}
head = head.next;
}
// 未找到目标结点,返回 null
return null;
}
/* Driver Code */
var target = 3;
/* 在数组中执行线性查找 */
var nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
var index = linearSearchArray(nums, target);
console.log("目标元素 3 的索引 = " + index);
/* 在链表中执行线性查找 */
var linkedList = new ListNode();
var head = linkedList.arrToLinkedList(nums);
var node = linearSearchLinkedList(head, target);
console.log("目标结点值 3 的对应结点对象为 " + node);

View File

@ -22,7 +22,7 @@ class ListNode {
*/
arrToLinkedList(arr) {
const dum = new ListNode(0);
const head = dum;
let head = dum;
for (const val of arr) {
head.next = new ListNode(val);
head = head.next;

View File

@ -1,8 +1,8 @@
'''
"""
File: array.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: linked_list.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: list.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: my_list.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: leetcode_two_sum.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: space_complexity.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: time_complexity.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: worst_best_time_complexity.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: binary_search.py
Created Time: 2022-11-26
Author: timi (xisunyy@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: hashing_search.py
Created Time: 2022-11-26
Author: timi (xisunyy@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: linear_search.py
Created Time: 2022-11-26
Author: timi (xisunyy@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: bubble_sort.py
Created Time: 2022-11-25
Author: timi (xisunyy@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: insertion_sort.py
Created Time: 2022-11-25
Author: timi (xisunyy@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: merge_sort.py
Created Time: 2022-11-25
Author: timi (xisunyy@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: quick_sort.py
Created Time: 2022-11-25
Author: timi (xisunyy@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: array_queue.py
Created Time: 2022-12-01
Author: Peng Chen (pengchzn@gmail.com)
'''
"""
import os.path as osp
import sys

View File

@ -1,8 +1,8 @@
'''
"""
File: array_stack.py
Created Time: 2022-11-29
Author: Peng Chen (pengchzn@gmail.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: deque.py
Created Time: 2022-11-29
Author: Peng Chen (pengchzn@gmail.com)
'''
"""
import os.path as osp
import sys

View File

@ -1,8 +1,8 @@
'''
"""
File: linkedlist_queue.py
Created Time: 2022-12-01
Author: Peng Chen (pengchzn@gmail.com)
'''
"""
import os.path as osp
import sys

View File

@ -1,8 +1,8 @@
'''
"""
File: linkedlist_stack.py
Created Time: 2022-11-29
Author: Peng Chen (pengchzn@gmail.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: queue.py
Created Time: 2022-11-29
Author: Peng Chen (pengchzn@gmail.com)
'''
"""
import os.path as osp
import sys

View File

@ -1,8 +1,8 @@
'''
"""
File: stack.py
Created Time: 2022-11-29
Author: Peng Chen (pengchzn@gmail.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: binary_search_tree.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: binary_tree.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: binary_tree_bfs.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: binary_tree_dfs.py
Created Time: 2022-11-25
Author: Krahets (krahets@163.com)
'''
"""
import sys, os.path as osp
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))

View File

@ -1,8 +1,8 @@
'''
"""
File: binary_tree.py
Created Time: 2021-12-11
Author: Krahets (krahets@163.com)
'''
"""
import collections

View File

@ -1,8 +1,8 @@
'''
"""
File: linked_list.py
Created Time: 2021-12-11
Author: Krahets (krahets@163.com)
'''
"""
class ListNode:
"""Definition for a singly-linked list node

View File

@ -1,8 +1,8 @@
'''
"""
File: print_util.py
Created Time: 2021-12-11
Author: Krahets (krahets@163.com), msk397 (machangxinq@gmail.com)
'''
"""
import copy
import queue

View File

@ -325,7 +325,7 @@ $T(n)$ 是个一次函数,说明时间增长趋势是线性的,因此易得
$$
T(n) \leq c \cdot f(n)
$$
则可认为 $f(n)$ 给出了 $T(n)$ 的一个渐近上界,记为
则可认为 $f(n)$ 给出了 $T(n)$ 的一个渐近上界,记为
$$
T(n) = O(f(n))
$$

View File

@ -10,10 +10,10 @@ comments: true
**「基本数据类型」是 CPU 可以直接进行运算的类型,在算法中直接被使用。**
- 「整数」根据不同的长度分为 byte, short, int, long ,根据算法需求选用,即在满足取值范围的情况下尽量减小内存空间占用
- 「浮点数」代表小数,根据长度分为 float, double ,同样根据算法的实际需求选用
- 「字符」在计算机中是以字符集的形式保存的char 的值实际上是数字,代表字符集中的编号,计算机通过字符集查表来完成编号到字符的转换。
- 「布尔」代表逻辑中的 ”是“ 与 ”否“ ,其占用空间需要具体根据编程语言确定,通常为 1 byte 或 1 bit
- 「整数」根据不同的长度分为 byte, short, int, long ,根据算法需求选用,即在满足取值范围的情况下尽量减小内存空间占用
- 「浮点数」代表小数,根据长度分为 float, double ,同样根据算法的实际需求选用
- 「字符」在计算机中是以字符集的形式保存的char 的值实际上是数字,代表字符集中的编号,计算机通过字符集查表来完成编号到字符的转换。占用空间与具体编程语言有关,通常为 2 bytes 或 1 byte
- 「布尔」代表逻辑中的 ”是“ 与 ”否“ ,其占用空间需要具体根据编程语言确定,通常为 1 byte 或 1 bit
!!! note "字节与比特"
@ -31,7 +31,7 @@ comments: true
| | long | 8 bytes | $-2^{63}$ ~ $2^{63} - 1$ | $0$ |
| 浮点数 | **float** | 4 bytes | $-3.4 \times 10^{38}$ ~ $3.4 \times 10^{38}$ | $0.0$ f |
| | double | 8 bytes | $-1.7 \times 10^{308}$ ~ $1.7 \times 10^{308}$ | $0.0$ |
| 字符 | **char** | 2 bytes | $0$ ~ $2^{16} - 1$ | $0$ |
| 字符 | **char** | 2 bytes / 1 byte | $0$ ~ $2^{16} - 1$ | $0$ |
| 布尔 | **boolean(bool)** | 1 byte / 1 bit | $\text{true}$ 或 $\text{false}$ | $\text{false}$ |
</div>
@ -63,7 +63,8 @@ comments: true
=== "Python"
```python title=""
""" Python 的 list 可以自由存储各种基本数据类型和对象 """
list = [0, 0.0, 'a', False]
```
=== "Go"
@ -93,7 +94,11 @@ comments: true
=== "C#"
```csharp title=""
/* 使用多种「基本数据类型」来初始化「数组」 */
int[] numbers = new int[5];
float[] decimals = new float[5];
char[] characters = new char[5];
bool[] booleans = new bool[5];
```
## 计算机内存

View File

@ -31,12 +31,23 @@ comments: true
- 算法是发挥数据结构优势的舞台。数据结构仅存储数据信息,结合算法才可解决特定问题。
- 算法有对应最优的数据结构。给定算法,一般可基于不同的数据结构实现,而最终执行效率往往相差很大。
如果将数据结构与算法比作「LEGO 乐高」,数据结构就是乐高「积木」,而算法就是把积木拼成目标形态的一系列「操作步骤」。
![relationship_between_data_structure_and_algorithm](what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png)
<p align="center"> Fig. 数据结构与算法的关系 </p>
如果将「LEGO 乐高」类比到「数据结构与算法」,那么可以得到下表所示的对应关系。
<div class="center-table" markdown>
| 数据结构与算法 | LEGO 乐高 |
| -------------- | ---------------------------------------- |
| 输入数据 | 未拼装的积木 |
| 数据结构 | 积木组织形式,包括形状、大小、连接方式等 |
| 算法 | 把积木拼成目标形态的一系列操作步骤 |
| 输出数据 | 积木模型 |
</div>
!!! tip "约定俗成的简称"
在实际讨论中,我们通常会将「数据结构与算法」直接简称为「算法」。例如,我们熟称的 LeetCode 算法题目,实际上同时考察了数据结构和算法两部分知识。

View File

@ -29,31 +29,24 @@ $$
首先,我们先采用“双闭区间”的表示,在数组 `nums` 中查找目标元素 `target` 的对应索引。
=== "Step 1"
![binary_search_step1](binary_search.assets/binary_search_step1.png)
=== "Step 2"
![binary_search_step2](binary_search.assets/binary_search_step2.png)
=== "Step 3"
![binary_search_step3](binary_search.assets/binary_search_step3.png)
=== "Step 4"
![binary_search_step4](binary_search.assets/binary_search_step4.png)
=== "Step 5"
![binary_search_step5](binary_search.assets/binary_search_step5.png)
=== "Step 6"
![binary_search_step6](binary_search.assets/binary_search_step6.png)
=== "Step 7"
![binary_search_step7](binary_search.assets/binary_search_step7.png)
二分查找“双闭区间”表示下的代码如下所示。
@ -146,7 +139,23 @@ $$
=== "JavaScript"
```js title="binary_search.js"
/* 二分查找(双闭区间) */
function binarySearch(nums, target) {
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
let i = 0, j = nums.length - 1;
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while (i <= j) {
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j]
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
j = m - 1;
else
return m; // 找到目标元素,返回其索引
}
// 未找到目标元素,返回 -1
return -1;
}
```
=== "TypeScript"
@ -260,7 +269,23 @@ $$
=== "JavaScript"
```js title="binary_search.js"
/* 二分查找(左闭右开) */
function binarySearch1(nums, target) {
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
let i = 0, j = nums.length;
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while (i < j) {
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j)
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
j = m;
else // 找到目标元素,返回其索引
return m;
}
// 未找到目标元素,返回 -1
return -1;
}
```
=== "TypeScript"
@ -337,7 +362,10 @@ $$
=== "JavaScript"
```js title=""
// (i + j) 有可能超出 int 的取值范围
let m = parseInt((i + j) / 2);
// 更换为此写法则不会越界
let m = parseInt(i + (j - i) / 2);
```
=== "TypeScript"

View File

@ -76,6 +76,18 @@ comments: true
=== "JavaScript"
```js title="linear_search.js"
/* 线性查找(数组) */
function linearSearchArray(nums, target) {
// 遍历数组
for (let i = 0; i < nums.length; i++) {
// 找到目标元素,返回其索引
if (nums[i] === target) {
return i;
}
}
// 未找到目标元素,返回 -1
return -1;
}
```
@ -167,7 +179,19 @@ comments: true
=== "JavaScript"
```js title="linear_search.js"
/* 线性查找(链表)*/
function linearSearchLinkedList(head, target) {
// 遍历链表
while(head) {
// 找到目标结点,返回之
if(head.val === target) {
return head;
}
head = head.next;
}
// 未找到目标结点,返回 null
return null;
}
```
=== "TypeScript"

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -377,3 +377,82 @@ comments: true
| 树的结点总数为 $n$ 时的高度 | $\log_2 (n+1) - 1$ | $n - 1$ |
</div>
## 二叉树表示方式 *
我们一般使用二叉树的「链表表示」,即存储单位为结点 `TreeNode` ,结点之间通过指针(引用)相连接。本文前述示例代码展示了二叉树在链表表示下的各项基本操作。
那能否可以用「数组表示」二叉树呢?答案是肯定的。先来分析一个简单案例,给定一个「完美二叉树」,将结点按照层序遍历的顺序编号(从 0 开始),那么可以推导得出父结点索引与子结点索引之间的「映射公式」:**设结点的索引为 $i$ ,则该结点的左子结点索引为 $2i + 1$ 、右子结点索引为 $2i + 2$** 。
**本质上,映射公式的作用就是链表中的指针**。对于层序遍历序列中的任意结点,我们都可以使用映射公式来访问子结点。因此,可以直接使用层序遍历序列(即数组)来表示完美二叉树。
![array_representation_mapping](binary_tree.assets/array_representation_mapping.png)
然而,完美二叉树只是个例,二叉树中间层往往存在许多空结点(即 `null` ),而层序遍历序列并不包含这些空结点,并且我们无法单凭序列来猜测空结点的数量和分布位置,**即理论上存在许多种二叉树都符合该层序遍历序列**。显然,这种情况无法使用数组来存储二叉树。
![array_representation_without_empty](binary_tree.assets/array_representation_without_empty.png)
为了解决此问题,考虑按照完美二叉树的形式来表示所有二叉树,**即在序列中使用特殊符号来显式地表示“空位”**。如下图所示,这样处理后,序列(数组)就可以唯一表示二叉树了。
=== "Java"
```java title=""
/* 二叉树的数组表示 */
// 使用 int 的包装类 Integer ,就可以使用 null 来标记空位
Integer[] tree = { 1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15 };
```
=== "C++"
```cpp title=""
/* 二叉树的数组表示 */
// 为了符合数据类型为 int ,使用 int 最大值标记空位
// 该方法的使用前提是没有结点的值 = INT_MAX
vector<int> tree = { 1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15 };
```
=== "Python"
```python title=""
“”“ 二叉树的数组表示 ”“”
# 直接使用 None 来表示空位
tree = [1, 2, 3, 4, None, 6, 7, 8, 9, None, None, 12, None, None, 15]
```
=== "Go"
```go title=""
```
=== "JavaScript"
```js title=""
```
=== "TypeScript"
```typescript title=""
```
=== "C"
```c title=""
```
=== "C#"
```csharp title=""
```
![array_representation_with_empty](binary_tree.assets/array_representation_with_empty.png)
回顾「完全二叉树」的满足条件,其只有最底层有空结点,并且最底层的结点尽量靠左,因而所有空结点都一定出现在层序遍历序列的末尾。**因为我们先验地确定了空位的位置,所以在使用数组表示完全二叉树时,可以省略存储“空位”**。“便于使用数组表示”也是完全二叉树受欢迎的原因之一。
![array_representation_complete_binary_tree](binary_tree.assets/array_representation_complete_binary_tree.png)
数组表示有两个优点: 一是不需要存储指针,节省空间;二是可以随机访问结点。然而,当二叉树中的“空位”很多时,数组中只包含很少结点的数据,空间利用率很低。

View File

@ -51,12 +51,12 @@ hide:
!!! quote ""
<p align="center"> “追风赶月莫停留,平芜尽处是春山 </p>
<p align="center"> “追风赶月莫停留,平芜尽处是春山 </p>
<p align="center"> 一起加油! </p>
---
## 推荐语
<h2 align="center"> 推荐语 </h2>
!!! quote
@ -64,7 +64,7 @@ hide:
**—— 邓俊辉,清华大学计算机系教授**
## 致谢
<h2 align="center"> 致谢 </h2>
感谢本开源书的每一位撰稿人,是他们的无私奉献让这本书变得更好,他们是: