Skip to content

Commit 5ba0b90

Browse files
朱孟申朱孟申
authored andcommitted
update
1 parent 6dc3a06 commit 5ba0b90

13 files changed

+791
-299
lines changed

basic_algorithm/.ipynb_checkpoints/sort-checkpoint.ipynb

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,15 @@
3434
"cell_type": "markdown",
3535
"metadata": {},
3636
"source": [
37-
"冒泡排序\n",
37+
"冒泡排序(其实应该叫沉底排序)\n",
38+
"\n",
39+
"1.1 算法描述\n",
40+
"\n",
41+
"比较相邻的元素。如果第一个比第二个大,就交换它们两个;\n",
42+
"对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;\n",
43+
"针对所有的元素重复以上的步骤,除了最后一个;\n",
44+
"重复步骤1~3,直到排序完成。\n",
45+
"\n",
3846
"时间复杂度最差O(n^2),最好O(n),平均O(n^2) 稳定排序,内排序\n",
3947
"冒泡排序时针对相邻元素之间的比较,可以将大的数慢慢“沉底”(数组尾部)\n",
4048
"\n",
@@ -57,7 +65,7 @@
5765
" def sortArray(self, nums: List[int]) -> List[int]:\n",
5866
" if nums is None: return nums\n",
5967
" n = len(nums)\n",
60-
" for i in range(n):\n",
68+
" for i in range(n): # n-1\n",
6169
" for j in range(n-i-1):\n",
6270
" if nums[j] > nums[j+1]:\n",
6371
" nums[j], nums[j+1] = nums[j+1], nums[j]\n",
@@ -68,10 +76,25 @@
6876
"cell_type": "markdown",
6977
"metadata": {},
7078
"source": [
71-
"插入排序是前面已排序数组找到插入的位置\n",
79+
"插入排序(这才是冒泡或者上浮排序, 虽然还是有点区别)\n",
80+
"\n",
81+
"是前面已排序数组找到插入的位置\n",
82+
"\n",
83+
"一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:\n",
84+
"\n",
85+
"从第一个元素开始,该元素可以认为已经被排序;\n",
86+
"取出下一个元素,在已经排序的元素序列中从后向前扫描;\n",
87+
"如果该元素(已排序)大于新元素,将该元素移到下一位置;\n",
88+
"重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;\n",
89+
"将新元素插入到该位置后;\n",
90+
"重复步骤2~5。\n",
91+
"\n",
7292
"3.4 算法分析\n",
93+
"\n",
7394
"最佳情况:T(n) = O(n)\n",
95+
"\n",
7496
"最坏情况:T(n) = O(n2)\n",
97+
"\n",
7598
"平均情况:T(n) = O(n2)"
7699
]
77100
},
@@ -99,6 +122,8 @@
99122
"source": [
100123
"希尔排序:我们来看下希尔排序的基本步骤,在此我们选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2,(n/2)/2…1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。\n",
101124
"\n",
125+
"简单而言排序的过程就是把插入排序的1换成gap。\n",
126+
"\n",
102127
"先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:\n",
103128
"步骤1:选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;\n",
104129
"步骤2:按增量序列个数k,对序列进行k 趟排序;\n",
@@ -218,7 +243,9 @@
218243
"\n",
219244
"时间复杂度:最好情况O(n * logn)——Partition函数每次恰好能均分序列,其递归树的深度就为.log2n.+1(.x.表示不大于x的最大整数),即仅需递归log2n次; 最坏情况O(n^2),每次划分只能将序列分为一个元素与其他元素两部分,这时的快速排序退化为冒泡排序,如果用数画出来,得到的将会是一棵单斜树,也就是说所有所有的节点只有左(右)节点的树;平均时间复杂度O(n*logn)\n",
220245
"\n",
221-
"快排由于是原地交换所以没有合并过程 传入的索引是存在的索引(如:0、length-1 等),越界可能导致崩溃"
246+
"快排由于是原地交换所以没有合并过程 传入的索引是存在的索引(如:0、length-1 等),越界可能导致崩溃\n",
247+
"\n",
248+
"[好理解的挖坑法](https://blog.csdn.net/qq_44750696/article/details/123822452)"
222249
]
223250
},
224251
{
@@ -227,35 +254,35 @@
227254
"metadata": {},
228255
"outputs": [],
229256
"source": [
230-
"def quick_sort(nums):\n",
231-
" n = len(nums)\n",
232-
"\n",
233-
" def quick(left, right):\n",
234-
" if left >= right:#递归到左和右一样,直接退出\n",
235-
" return nums\n",
236-
" pivot = left\n",
237-
" i = left\n",
238-
" j = right\n",
239-
" while i < j:\n",
240-
" #先右后左是根据挖坑法的顺序,而等号比较其实是无所谓的,除了不能一个等于号都没有以外(两边相同会造成死循环),一个等于号或者两个都可以,\n",
241-
" #为了方便记忆(我也懒得一个个验证)就用两个等号了。\n",
242-
" #原算法是上边是>下边是<=\n",
243-
" while i < j and nums[j] >= nums[pivot]:#从右向左找第一个小于x的数\n",
244-
" #while i < j and nums[j] > nums[pivot]:#从右向左找第一个小于等于x的数\n",
245-
" j -= 1\n",
246-
" while i < j and nums[i] <= nums[pivot]:#从左向右找第一个大于x的数,因为是大于x的数所以跳过了pivot,相当于把pivot空出\n",
247-
" i += 1\n",
248-
" nums[i], nums[j] = nums[j], nums[i]#两者交换\n",
249-
" nums[pivot], nums[j] = nums[j], nums[pivot]#把pivot放到停止的位置(按挖坑法之前小于pivot的数已经被挖走,此处是空的,\n",
250-
" #按交换法该位置就是pivot应该在的位置,且该位置的数一定 <= pivot,所以转换到左边是一定的)\n",
251-
" #i = j 时数一定<= pivot 的原因\n",
252-
" #1. 若j停下了,那一定说明i往右推和j会合的数的就是<= pivot的数\n",
253-
" #2. 若j没停下,最后势必会找到一个<=pivot的数(因为上一轮i,j交换,i指向的位置<=pivot; 若是第一轮,i指向的位置等于pivot)\n",
254-
" quick(left, j - 1)\n",
255-
" quick(j + 1, right)\n",
256-
" return nums\n",
257-
"\n",
258-
" return quick(0, n - 1)"
257+
"class Solution:\n",
258+
" def sortArray(self, nums: List[int]) -> List[int]:\n",
259+
" n = len(nums)\n",
260+
" def quickSort(left, right):\n",
261+
" if left >= right: # 递归到左和右一样,直接退出\n",
262+
" return\n",
263+
" # 随机选择pivot是为了尽量避免排序一个有序逆序列表时,一个子序列是空,一个子序列是剩下所有\n",
264+
" # 最后导致出现最差结果 O(n^2)\n",
265+
" pivotIdx = random.randint(left, right) \n",
266+
" # pivot = left\n",
267+
" pivot = nums[pivotIdx]\n",
268+
" nums[left], nums[pivotIdx] = nums[pivotIdx], nums[left] # pivot放置到最左边\n",
269+
"\n",
270+
" i, j = left, right\n",
271+
" while i < j:\n",
272+
" while i < j and nums[j] >= pivot: # 找到右边第一个<pivot的元素\n",
273+
" j -= 1\n",
274+
" nums[i] = nums[j] # 并将其移动到i处\n",
275+
"\n",
276+
" while i < j and nums[i] <= pivot: # 找到左边第一个>pivot的元素\n",
277+
" i += 1\n",
278+
" nums[j] = nums[i] # 并将其移动到j处\n",
279+
" \n",
280+
" nums[i] = pivot # pivot放置到中间 i=j 处\n",
281+
" quickSort(left, i - 1)\n",
282+
" quickSort(i+1, right)\n",
283+
" \n",
284+
" quickSort(0, n - 1)\n",
285+
" return nums"
259286
]
260287
},
261288
{
@@ -392,13 +419,13 @@
392419
"source": [
393420
"## 题目\n",
394421
"### [kth-largest-element-in-an-array](https://leetcode-cn.com/problems/kth-largest-element-in-an-array/)\n",
395-
"### [链接](http://localhost:8888/notebooks/algorithm-pattern-python/data_structure/%E5%A0%86%E7%AC%94%E8%AE%B0.ipynb)\n"
422+
"### [链接](http://localhost:8888/notebooks/algorithm-pattern-python/data_structure/%E5%A0%86%E7%AC%94%E8%AE%B0_%E6%9C%AA%E5%AE%8C%E6%88%90.ipynb)\n"
396423
]
397424
}
398425
],
399426
"metadata": {
400427
"kernelspec": {
401-
"display_name": "Python 3",
428+
"display_name": "Python 3 (ipykernel)",
402429
"language": "python",
403430
"name": "python3"
404431
},
@@ -412,7 +439,7 @@
412439
"name": "python",
413440
"nbconvert_exporter": "python",
414441
"pygments_lexer": "ipython3",
415-
"version": "3.7.0"
442+
"version": "3.9.15"
416443
}
417444
},
418445
"nbformat": 4,

0 commit comments

Comments
 (0)