Skip to content

Commit 70b824c

Browse files
committed
Partial change some characters
1 parent 22ceb7a commit 70b824c

File tree

22 files changed

+64
-64
lines changed

22 files changed

+64
-64
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
169169
- 時間、空間複雜度
170170
- 使用場景,什麼時候用
171171
- 自己嘗試實現,如果抛開影片自己寫起來有困難可以反复多看幾次影片,一定要自己手動實現。很多面試可能會讓手寫。一次不行就看完原理後多實践幾次,直到能自己独立完成。
172-
- 每章講義後面都會有我設計的幾個小問題,最好能够回答上來。同時還有原始碼练习題,你可以挑戰下自己的掌握程度。
172+
- 每章講義後面都會有我設計的幾個小問題,最好能够回答上來。同時還有原始碼練習題,你可以挑戰下自己的掌握程度。
173173
- 最好按照顺序循序漸進,每章都會有铺垫和联系,後面的章節可能會使用到前面提到的數據結構
174-
- 根據自己的基礎結合我列舉的教材和影片學習,第一次理解不了的可以反复多看幾次,多編寫原始碼练习到熟练為止
174+
- 根據自己的基礎結合我列舉的教材和影片學習,第一次理解不了的可以反复多看幾次,多編寫原始碼練習到熟练為止
175175

176176
## 課程目標
177177
掌握基本的算法和數據結構原理,能独立使用 Python 語言實現,能在日常開發中灵活選用數據結構。

docs/03_链表/linked_list.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class LinkedList(object):
3333
"""
3434
```
3535
實現我們會在影片中用画图來模擬並且手動原始碼實現,原始碼裡我們會標识每個步骤的時間複雜度。這裡請高度集中精力,
36-
雖然鏈表的思想很簡單,但是想要正確写對鏈表的操作原始碼可不容易,稍不留神就可能丢失一些步骤。
36+
雖然鏈表的思想很簡單,但是想要正確寫對鏈表的操作原始碼可不容易,稍不留神就可能丢失一些步骤。
3737
這裡我們還是會用簡單的單測來驗證原始碼是否按照預期工作。
3838

3939
來看下時間複雜度:
@@ -71,7 +71,7 @@ class Node(object):
7171
- 直接删除節點,當然如果给的是一個值,我們還是需要查找這個值在哪個節點? - 但是如果给了一個節點,我們把它拿掉,直接讓它的前後節點互相指過去不就行了?哇欧,删除就是 O(1) 了,兩步操作就行啦
7272

7373
好,废話不多說,我們在影片裡介绍怎麼實現一個双鏈表 ADT。你可以直接在本項目的 `docs/03_鏈表/double_link_list.py` 找到原始碼。
74-
最後讓我們看下它的時間複雜度:(這裡 CircularDoubleLinkedList 取大写字母缩写為 cdll)
74+
最後讓我們看下它的時間複雜度:(這裡 CircularDoubleLinkedList 取大寫字母缩寫為 cdll)
7575

7676
循環双端鏈表操作 | 平均時間複雜度 |
7777
---------------------------------------|----------------|
@@ -101,7 +101,7 @@ cdll.tailnode() | O(1) |
101101

102102
反轉鏈表 [reverse-linked-list](https://leetcode.com/problems/reverse-linked-list/)
103103

104-
這裡有一道關於 LRU 的练习题你可以嘗試下
104+
這裡有一道關於 LRU 的練習题你可以嘗試下
105105
[LRU Cache](https://leetcode.com/problems/lru-cache/description/)
106106

107107
合並兩個有序鏈表 [merge-two-sorted-lists](/https://leetcode.com/problems/merge-two-sorted-lists/submissions/)

docs/03_链表/lru_cache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def fib(n):
1313

1414

1515
"""
16-
下邊就來写一個缓存装饰器來優化它。傳统方法是用個數組记录之前計算過的值,但是這種方式不够 Pythonic
16+
下邊就來寫一個缓存装饰器來優化它。傳统方法是用個數組记录之前計算過的值,但是這種方式不够 Pythonic
1717
"""
1818

1919

@@ -127,7 +127,7 @@ def test():
127127
print(time.time() - beg)
128128

129129

130-
# TODO 要怎麼给 lru 写單測
130+
# TODO 要怎麼给 lru 寫單測
131131

132132
if __name__ == '__main__':
133133
test()

docs/04_队列/deque.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# 留给讀者练习,如果實在想不出,在第 5 章堆疊裡 stack.py 會有實現
1+
# 留给讀者練習,如果實在想不出,在第 5 章堆疊裡 stack.py 會有實現

docs/04_队列/queue.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ for i in range(100):
7979
- remove(node) # O(1)
8080

8181
啊哈,似乎删除頭尾都可以啦,而且都是 O(1) 的,完美。
82-
交给你一個艰巨的任务,實現双端陣列 Deque() ADT。你可以参考前幾章的任何原始碼,挑战一下這個任务,别忘记写單元測試呦。當然如果没想出來也没關系,後面我們實現堆疊的時候還會用到它,那裡我們會實現這個原始碼。
82+
交给你一個艰巨的任务,實現双端陣列 Deque() ADT。你可以参考前幾章的任何原始碼,挑战一下這個任务,别忘记寫單元測試呦。當然如果没想出來也没關系,後面我們實現堆疊的時候還會用到它,那裡我們會實現這個原始碼。
8383

8484

8585
# 思考题

docs/05_栈/stack.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ infinite_fib(10)
5050
當我們不知道使用什麼數據結構來解決問题的時候,《程序员面試金典》這本书的第六章提到了一種方式叫做『數據結構頭腦風暴法』。
5151
這種笨方法就是快速過一遍數據結構的列表,然後逐一嘗試各種數據結構看看哪個最適合。
5252

53-
在你實現一個更高级的數據結構的時候,如果腦子没有思路,不妨嘗試下這個方法,迅速過一遍你所知道的數據結構,看看哪種最適合。(從每個操作的時間複雜度和空間複雜度分析寻找最優解)
53+
在你實現一個更高级的數據結構的時候,如果腦子没有思路,不妨嘗試下這個方法,迅速過一遍你所知道的數據結構,看看哪種最適合。(從每個操作的時間複雜度和空間複雜度分析尋找最優解)
5454

5555
# 思考题
5656
- 上一章我們用數組實現了陣列,其實也能用數組來實現堆疊,你能自己用數組來實現一個堆疊的 ADT 嗎?
5757
- 實際上借助 python 内置的 list/collections.deque 結構就很容易實現一個堆疊,請你嘗試實現,本章我們全部使用自己编寫的數據結構而没用到 python 内置的數據結構。
5858
- 這裡我們自己實現了 Deque,你能用 python 内置的 collections.deque 實現堆疊嗎?有輪子能直接用的話看起來就簡單多了,這裡我們為了學習數據結構的實現就避免了直接使用内置結構
5959
- 哪些經典算法裡使用到了堆疊呢?
6060

61-
# Leetcode 练习
61+
# Leetcode 練習
6262

6363
https://leetcode.com/problems/implement-queue-using-stacks/

docs/06_算法分析/big_o.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,4 @@ $n!$ | 階乘 | 旅行商問題 |
119119
如果你對數學感興趣,建議你閱讀《算法導論》『函數的增長』這一節 和《Data Structures and Algorithms in Python》第4章。
120120

121121

122-
(本章我用了 [MathJax](https://www.zybuluo.com/codeep/note/163962) 來书写一些簡單的數學公式,使用 "$"包含起來的就是數學公式)
122+
(本章我用了 [MathJax](https://www.zybuluo.com/codeep/note/163962) 來书寫一些簡單的數學公式,使用 "$"包含起來的就是數學公式)

docs/07_哈希表/hashtable.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ h(226) = 226 % M = 5
3333
h(903) = 903 % M = 6
3434
h(388) = 388 % M = 11
3535
```
36-
下邊我画個图演示整個插入過程(纯手工绘制,原谅我字写得不太優雅):
36+
下邊我画個图演示整個插入過程(纯手工绘制,原谅我字寫得不太優雅):
3737

3838
![](./insert_hash.png)
3939

@@ -46,15 +46,15 @@ h(388) = 388 % M = 11
4646
![](./insert_hash_chaining.png)
4747

4848
這樣就用鏈表解決了衝突問題,但是如果哈希函數選不好的話,可能就导致衝突太多一個鏈变得太長,這樣查找就不再是 O(1) 的了。
49-
還有一種叫做開放寻址法(open addressing),它的基本思想是當一個槽被占用的時候,採用一種方式來寻找下一個可用的槽
49+
還有一種叫做開放尋址法(open addressing),它的基本思想是當一個槽被占用的時候,採用一種方式來尋找下一個可用的槽
5050
(這裡槽指的是數組中的一個位置),根據找下一個槽的方式不同,分為:
5151

5252
- 線性探查(linear probing): 當一個槽被占用,找下一個可用的槽。 $ h(k, i) = (h^\prime(k) + i) \% m, i = 0,1,...,m-1 $
5353
- 二次探查(quadratic probing): 當一個槽被占用,以二次方作為偏移量。 $ h(k, i) = (h^\prime(k) + c_1 + c_2i^2) \% m , i=0,1,...,m-1 $
5454
- 双重散列(double hashing): 重新計算 hash 結果。 $ h(k,i) = (h_1(k) + ih_2(k)) \% m $
5555

5656
我們選一個簡單的二次探查函數 $ h(k, i) = (home + i^2) \% m $,它的意思是如果
57-
遇到了衝突,我們就在原始計算的位置不断加上 i 的平方。我写了段原始碼來模擬整個計算下標的過程
57+
遇到了衝突,我們就在原始計算的位置不断加上 i 的平方。我寫了段原始碼來模擬整個計算下標的過程
5858

5959
```py
6060
inserted_index_set = set()
@@ -168,7 +168,7 @@ class HashTable(object):
168168
pass
169169
```
170170

171-
具體的實現和原始碼编写在影片裡講解。這個原始碼可不太好實現,稍不留神就會有错,我們還是通過编写單元測試驗證原始碼的正確性
171+
具體的實現和原始碼编寫在影片裡講解。這個原始碼可不太好實現,稍不留神就會有错,我們還是通過编寫單元測試驗證原始碼的正確性
172172

173173
# 思考题
174174
- 請你分析下哈希表插入和删除元素的平均時間複雜度是多少?我們都實現原始碼了,相信這個問題你可以回答上來

docs/08_字典/dict.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# 字典 dict
22

33
上一章我們介绍了哈希表,其實 python 内置的 dict 就是用哈希表實現的,所以這一章實現 dict 就非常簡單了。
4-
當然 cpython 使用的是 c 语言實現的,远比我們写的复杂得多 (cpython/Objects/dictobject.c)。
5-
上一章我們用 python 自己写的一個 Array 來代表定長數組,然後用它實現的 HashTable,它支持三個最基本的方法
4+
當然 cpython 使用的是 c 语言實現的,远比我們寫的复杂得多 (cpython/Objects/dictobject.c)。
5+
上一章我們用 python 自己寫的一個 Array 來代表定長數組,然後用它實現的 HashTable,它支持三個最基本的方法
66

77
- add(key ,value): 有 key 则更新,否则插入
88
- get(key, default=None): 或者 key 的值,不存在返回默认值 None
@@ -23,7 +23,7 @@ class DictADT(HashTable):
2323
pass
2424
```
2525

26-
影片裡我們將演示如何實現這些方法,並且写單測驗證正確性
26+
影片裡我們將演示如何實現這些方法,並且寫單測驗證正確性
2727

2828
# Hashable
2929
作為 dict 的 key 必须是可哈希的,也就是說不能是 list 等可变對象。不信你在 ipython 裡運行如下原始碼:

docs/09_集合/set.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class SetADT(HashTable):
4343
- 集合判断一個元素是否存在的時間複雜度是多少?
4444
- 集合的元素 key 需要满足什麼概念?可变對象可以嗎?
4545
- 請你在 SetADT 基础上實現集合的 remove 操作和 pop 操作
46-
- 你能嘗試實現對称差操作嗎?這裡我没有實現,留给你作為练习
46+
- 你能嘗試實現對称差操作嗎?這裡我没有實現,留给你作為練習
4747
- 你知道如何重载 python 的内置運算符嗎?這裡我們實現 set 的集合操作就是用到了重载,請閱讀相關 python 文档。
4848
- 當元素個數不多的時候,我們可以用 set 來判重,但是如果是大量元素會非常耗费記憶體。請你了解下 Bloom Filter
4949

docs/10_递归/recursion.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
![](./fact.png)
1818

19-
我們很容易根據它的定義写出這樣一個遞迴函數,因為它本身就是遞迴定義的。
19+
我們很容易根據它的定義寫出這樣一個遞迴函數,因為它本身就是遞迴定義的。
2020

2121
```py
2222
def fact(n):
@@ -25,7 +25,7 @@ def fact(n):
2525
else:
2626
return n * fact(n-1)
2727
```
28-
看吧,幾乎完全是按照定義來写的。我們來看下遞迴函數的幾個特點:
28+
看吧,幾乎完全是按照定義來寫的。我們來看下遞迴函數的幾個特點:
2929

3030
- 遞迴必须包含一個基本的出口(base case),否则就會無限遞迴,最终导致堆疊溢出。比如這裡就是 n == 0 返回 1
3131
- 遞迴必须包含一個可以分解的問題(recursive case)。 要想求得 fact(n),就需要用 n * fact(n-1)
@@ -34,7 +34,7 @@ def fact(n):
3434

3535
# 調用堆疊
3636
看了上一個例子你可能覺得遞迴好簡單,先别着急,我們再舉個簡單的例子,上邊我們並没有講遞迴如何工作的。
37-
假如讓你輸出從 1 到 10 這十個數字,如果你是個正常人的話,我想你的第一反应都是這麼写
37+
假如讓你輸出從 1 到 10 這十個數字,如果你是個正常人的話,我想你的第一反应都是這麼寫
3838

3939
```py
4040
def print_num(n):
@@ -46,7 +46,7 @@ if __name__ == '__main__':
4646
print_num(10)
4747
```
4848

49-
我們嘗試写一個遞迴版本,不就是自己調用自己嘛:
49+
我們嘗試寫一個遞迴版本,不就是自己調用自己嘛:
5050

5151
```py
5252
def print_num_recursive(n):

docs/11_线性查找与二分查找/search.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ assert linear_search_recusive(number_list, 8) == -1
5151
assert linear_search_recusive(number_list, 7) == 7
5252
assert linear_search_recusive(number_list, 0) == 0
5353
```
54-
這裡的 assert 我多写了幾個,包括正常情况、异常情况和邊界值等,因為遞迴比较容易出错。注意這裡的兩個遞迴出口。
54+
這裡的 assert 我多寫了幾個,包括正常情况、异常情况和邊界值等,因為遞迴比较容易出错。注意這裡的兩個遞迴出口。
5555
當然業務原始碼裡如果碰到這種問題我們肯定是選上邊最直白的方式來實現,要不你的同事肯定想打你。
5656

5757
# 二分查找
@@ -61,7 +61,7 @@ assert linear_search_recusive(number_list, 0) == 0
6161
- 一尺之棰,日取其半,万世不竭
6262
- 有些民間股神,告诉一堆人某個股票會涨,告诉另一半人會跌。後來真涨了,慢慢又告诉信了他的一半人另一個股票會涨,另一半說會跌。就這樣韭菜多了总有一些人信奉他為股神。。。
6363

64-
其實之前写過博客[《抱歉,我是開發,你居然讓我写單測[影片]](https://zhuanlan.zhihu.com/p/35352024)講過二分查找,當時主要是為了引入單元測試這個概念的,因為很多不正规的項目原始碼很糙,更别說写單測了。這裡我就直接贴原始碼啦
64+
其實之前寫過博客[《抱歉,我是開發,你居然讓我寫單測[影片]](https://zhuanlan.zhihu.com/p/35352024)講過二分查找,當時主要是為了引入單元測試這個概念的,因為很多不正规的項目原始碼很糙,更别說寫單測了。這裡我就直接贴原始碼啦
6565

6666
```py
6767
def binary_search(sorted_array, val):
@@ -98,13 +98,13 @@ def test_binary_search():
9898

9999

100100
# 思考题
101-
- 给你個挑战,用遞迴來實現本章的二分查找。你要十分注意邊界條件,注意用單測測試呦,在你写原始碼的時候,可能會碰到邊界問題或者無穷遞迴等。 如果你想不起來,可以看看本章的原始碼示例
101+
- 给你個挑战,用遞迴來實現本章的二分查找。你要十分注意邊界條件,注意用單測測試呦,在你寫原始碼的時候,可能會碰到邊界問題或者無穷遞迴等。 如果你想不起來,可以看看本章的原始碼示例
102102
- 二分查找有一個变形,比如我們想在一個有序數組中插入一個值之後,數組仍保持有序,請你找出這個位置。(bisect 模塊)
103103

104104

105105
# 延伸閱讀
106106
這裡没给鏈接,請善用 google 等搜索引擎和 Dash(mac) 等文档查询工具,在你學習原始碼的過程中你會非常頻繁地使用它們。
107-
或者如果你有時間也可以跳轉到這些模塊的源碼,看看它們的實現方式。標准库都是些高手写的,肯定能學到一些姿势。
107+
或者如果你有時間也可以跳轉到這些模塊的源碼,看看它們的實現方式。標准库都是些高手寫的,肯定能學到一些姿势。
108108

109109
- 閱讀 python 文档關於二分的 bisect 模塊。
110110
- 閱讀 python 文档 itertools 相關模塊和常見的幾個函數 takewhile, dropwhile, from_iterable, count, tee 等用法

docs/13_高级排序算法/quick_sort.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
![](./quick_sort.png)
1616

17-
根據這個想法我們可以快速写出快排的原始碼,簡直就是在翻译上邊的描述:
17+
根據這個想法我們可以快速寫出快排的原始碼,簡直就是在翻译上邊的描述:
1818

1919
```py
2020
def quicksort(array):
@@ -33,7 +33,7 @@ def test_quicksort():
3333
random.shuffle(seq)
3434
assert quicksort(seq) == sorted(seq)
3535
```
36-
是不是很簡單,下次面試官讓你手写快排你再写不出來就有點不太合适啦。 當然這個實現有兩個不好的地方:
36+
是不是很簡單,下次面試官讓你手寫快排你再寫不出來就有點不太合适啦。 當然這個實現有兩個不好的地方:
3737

3838
- 第一是它需要额外的存儲空間,我們想實現 inplace 原地排序。
3939
- 第二是它的 partition 操作每次都要兩次遍历整個數組,我們想改善一下。
@@ -102,7 +102,7 @@ T(n) = 2T(n/2) + n
102102
- 最坏的情况下快排的時間複雜度是多少?什麼時候會發生這種情况?
103103
- 我們實現的快排是稳定的啵?
104104
- 選择基准值如果選不好就可能导致複雜度升高,算导中提到了一種『median of 3』策略,就是說選择 pivot 的時候 從子數組中随機選三個元素,再取它的中位數,你能實現這個想法嗎?這裡我們的原始碼很簡單地取了第一個元素作為 pivot
105-
- 利用快排中的 partition 操作,我們還能實現另一個算法,nth_element,快速查找一個無序數組中的第 n 大元素,請你嘗試實現它並编写單測。其實這個函數是 C++ STL 中的一個函數。
105+
- 利用快排中的 partition 操作,我們還能實現另一個算法,nth_element,快速查找一個無序數組中的第 n 大元素,請你嘗試實現它並编寫單測。其實這個函數是 C++ STL 中的一個函數。
106106
- 你知道 Python 内置的 sorted 如何實現的嗎?請你 Google 相關資料了解下。很多内置的排序都使用了快排的改良版。
107107

108108

@@ -127,5 +127,5 @@ T(n) = 2T(n/2) + n
127127

128128
# Leetcode
129129

130-
無序數組寻找第 k 大的數字,不止一種方法。
130+
無序數組尋找第 k 大的數字,不止一種方法。
131131
https://leetcode.com/problems/kth-largest-element-in-an-array/description/

0 commit comments

Comments
 (0)