Skip to content

Commit cc6ed37

Browse files
committed
Merge branch 'master' of github.com:facert/python-data-structure-cn
2 parents 31d440b + 09843d0 commit cc6ed37

File tree

2 files changed

+7
-7
lines changed
  • 2.算法分析/2.4.一个乱序字符串检查的例子
  • 6.树和树的算法/6.7.树的遍历

2 files changed

+7
-7
lines changed

2.算法分析/2.4.一个乱序字符串检查的例子/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
## 2.4.一个乱序字符串检查的例子
22

3-
显示不同量级的算法的一个很好的例子是字符串的乱序检查。一个字符串是另一个字符串的乱序。如果第二个字符串只是第一个的重新排列,例如,'heart' 和 'earth' 就是乱序字符串。'python' 和 'typhon' 也是。为了简单起见,我们假设所讨论的两个字符串具有相等的长度,并且他们由 26 个小写字母集合组成。我们的目标是写一个布尔函数,它将两个字符串做参数并返回它们是不是回文
3+
显示不同量级的算法的一个很好的例子是字符串的乱序检查。乱序字符串是指一个字符串只是另一个字符串的重新排列。例如,'heart' 和 'earth' 就是乱序字符串。'python' 和 'typhon' 也是。为了简单起见,我们假设所讨论的两个字符串具有相等的长度,并且他们由 26 个小写字母集合组成。我们的目标是写一个布尔函数,它将两个字符串做参数并返回它们是不是乱序
44

55
### 2.4.1.解法1:检查
6-
我们对乱序问题的第一个解法是检查第一个字符串是不是出现在第二个字符串中。如果可以检验到每一个字符,那两个字符串一定是回文。可以通过用 None 替换字符来完成检查。但是,由于 Python 字符串是不可变的,所以第一步是将第二个字符串转换为列表。第一个字符串中的每个字符可以通过检查在第二个列表中检查元素是否存在,如果存在,替换成 None。见 ActiveCode1
6+
我们对乱序问题的第一个解法是检查第一个字符串是不是出现在第二个字符串中。如果可以检验到每一个字符,那这两个字符串一定是乱序。可以通过用 None 替换字符来了解一个字符是否完成检查。但是,由于 Python 字符串是不可变的,所以第一步是将第二个字符串转换为列表。检查第一个字符串中的每个字符是否存在于第二个列表中,如果存在,替换成 None。见 ActiveCode1
77

88
````
99
def anagramSolution1(s1,s2):
@@ -41,7 +41,7 @@ print(anagramSolution1('abcd','dcba'))
4141

4242
### 2.4.2.解法2:排序和比较
4343

44-
另一个解决方案是利用这么一个事实即使 s1,s2 不同,它们只有由完全相同的字符组成,它们才是回文。所以,如果我们按照字母顺序排列每个字符串,从 a 到 z,如果两个字符串相同,则这两个字符串为回文。见 ActiveCode2。
44+
另一个解决方案是利用这么一个事实即使 s1,s2 不同,它们都是由完全相同的字符组成的。所以,我们按照字母顺序从 a 到 z 排列每个字符串,如果两个字符串相同,那这两个字符串就是乱序字符串。见 ActiveCode2。
4545

4646
````
4747
def anagramSolution2(s1,s2):
@@ -66,17 +66,17 @@ print(anagramSolution2('abcde','edcba'))
6666
````
6767
*ActiveCode2*
6868

69-
首先你可能认为这个算法是 O(n),因为只有一个简单的迭代来比较排序后的 n 个字符。但是,调用 Python 排序不是没有成本。正如我们将在后面的章节中看到的,排序通常是 O(n^2 ) 或 O(nlogn)。所以排序操作比迭代花费更多。最后该算法跟排序过程有同样的量级。
69+
首先你可能认为这个算法是 O(n),因为只有一个简单的迭代来比较排序后的 n 个字符。但是,调用 Python 排序不是没有成本。正如我们将在后面的章节中看到的,排序通常是 O(n^2) 或 O(nlogn)。所以排序操作比迭代花费更多。最后该算法跟排序过程有同样的量级。
7070

7171
### 2.4.3.解法3: 穷举法
7272

73-
解决这类问题的强力方法是穷举所有可能性。对于回文检测,我们可以生成 s1 的所有乱序字符串列表,然后查看是不是有 s2。这种方法有一点困难。当 s1 生成所有可能的字符串时,第一个位置有 n 种可能,第二个位置有 n-1 种,第三个位置有 n-3 种,等等。总数为 n∗(n−1)∗(n−2)∗...∗3∗2∗1n∗(n−1)∗(n−2)∗...∗3∗2∗1, 即 n!。虽然一些字符串可能是重复的,程序也不可能提前知道这样,所以他仍然会生成 n! 个字符串。
73+
解决这类问题的强力方法是穷举所有可能性。对于乱序检测,我们可以生成 s1 的所有乱序字符串列表,然后查看是不是有 s2。这种方法有一点困难。当 s1 生成所有可能的字符串时,第一个位置有 n 种可能,第二个位置有 n-1 种,第三个位置有 n-3 种,等等。总数为 n∗(n−1)∗(n−2)∗...∗3∗2∗1n∗(n−1)∗(n−2)∗...∗3∗2∗1, 即 n!。虽然一些字符串可能是重复的,程序也不可能提前知道这样,所以他仍然会生成 n! 个字符串。
7474

7575
事实证明,n! 比 n^2 增长还快,事实上,如果 s1 有 20个字符长,则将有 20! = 2,432,902,008,176,640,000 个字符串产生。如果我们每秒处理一种可能字符串,那么需要 77,146,816,596 年才能过完整个列表。所以这不是很好的解决方案。
7676

7777
### 2.4.4.解法4: 计数和比较
7878

79-
我们最终解决回文的方法是利用两个乱序字符串具有相同的 a, b, c 等等的事实。我们首先计算的是每个字母出现的次数。由于有 26 个可能的字符,我们就用 一个长度为 26 的列表,每个可能的字符占一个位置。每次看到一个特定的字符,就增加该位置的计数器。最后如果两个列表的计数器一样,则字符串为乱序字符串。见 ActiveCode 3
79+
我们最终的解决方法是利用两个乱序字符串具有相同数目的 a, b, c 等字符的事实。我们首先计算的是每个字母出现的次数。由于有 26 个可能的字符,我们就用 一个长度为 26 的列表,每个可能的字符占一个位置。每次看到一个特定的字符,就增加该位置的计数器。最后如果两个列表的计数器一样,则字符串为乱序字符串。见 ActiveCode 3
8080

8181
```` python
8282
def anagramSolution4(s1,s2):

6.树和树的算法/6.7.树的遍历/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## 6.7.树的遍历
22

3-
现在我们已经检查了树数据结构的基本功能,现在是查看树的一些额外使用模式的时候了。这些使用模式可以分为我们访问树的节点的三种方式。有三种常用的模式来访问树中的所有节点。这些模式之间的差异是每个节点被访问的顺序。我们称这种访问节点方式为“遍历”。我们将看到的三个遍历称为`前序,后序``后序` 。让我们通过更仔细地定义这三个遍历,然后看看这些模式有用的一些例子。
3+
现在我们已经检查了树数据结构的基本功能,现在是查看树的一些额外使用模式的时候了。这些使用模式可以分为我们访问树的节点的三种方式。有三种常用的模式来访问树中的所有节点。这些模式之间的差异是每个节点被访问的顺序。我们称这种访问节点方式为“遍历”。我们将看到的三个遍历称为`前序,中序``后序` 。让我们通过更仔细地定义这三个遍历,然后看看这些模式有用的一些例子。
44

55
**前序**
66
在前序遍历中,我们首先访问根节点,然后递归地做左侧子树的前序遍历,随后是右侧子树的递归前序遍历。

0 commit comments

Comments
 (0)