Skip to content

Commit 4eae605

Browse files
author
zhumengs
committed
以前刷的踢
1 parent aa95b27 commit 4eae605

12 files changed

+9180
-0
lines changed
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"选择排序\n",
8+
"时间复杂度都是O(n^2),不稳定\n",
9+
"是表现最稳定的排序算法之一 ,因为无论什么数据进去都是O(n2)的时间复杂度 \n",
10+
"选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n - 1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等 的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。\n",
11+
"\n",
12+
"它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾"
13+
]
14+
},
15+
{
16+
"cell_type": "code",
17+
"execution_count": null,
18+
"metadata": {},
19+
"outputs": [],
20+
"source": [
21+
"class Solution:\n",
22+
" def sortArray(self, nums: List[int]) -> List[int]:\n",
23+
" n = len(nums)\n",
24+
" for i in range(n-1):\n",
25+
" minIndex = i \n",
26+
" for j in range(i+1,n):\n",
27+
" if nums[minIndex] > nums[j]:\n",
28+
" minIndex = j\n",
29+
" nums[minIndex], nums[i] = nums[i], nums[minIndex]\n",
30+
" return nums"
31+
]
32+
},
33+
{
34+
"cell_type": "markdown",
35+
"metadata": {},
36+
"source": [
37+
"冒泡排序\n",
38+
"时间复杂度最差O(n^2),最好O(n) 稳定排序,内排序\n",
39+
"冒泡排序时针对相邻元素之间的比较,可以将大的数慢慢“沉底”(数组尾部)\n",
40+
"\n",
41+
" 最佳情况和最坏情况都是θ(n^2);\n",
42+
"\n",
43+
"但是如果在算法中加入didSwap标记\n",
44+
"\n",
45+
"如果循环没有进行交换,可以理解为数组已经排好序,同时退出排序;\n",
46+
"\n",
47+
"此时最佳情况为数组本来就按要求排好序,只需要θ(n)就可以结束算法;"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": null,
53+
"metadata": {},
54+
"outputs": [],
55+
"source": [
56+
"class Solution:\n",
57+
" def sortArray(self, nums: List[int]) -> List[int]:\n",
58+
" if nums is None: return nums\n",
59+
" n = len(nums)\n",
60+
" for i in range(n):\n",
61+
" for j in range(n-i-1):\n",
62+
" if nums[j] > nums[j+1]:\n",
63+
" nums[j], nums[j+1] = nums[j+1], nums[j]\n",
64+
" return nums"
65+
]
66+
},
67+
{
68+
"cell_type": "markdown",
69+
"metadata": {},
70+
"source": [
71+
"插入排序是前面已排序数组找到插入的位置\n",
72+
"3.4 算法分析\n",
73+
"最佳情况:T(n) = O(n)\n",
74+
"最坏情况:T(n) = O(n2)\n",
75+
"平均情况:T(n) = O(n2)"
76+
]
77+
},
78+
{
79+
"cell_type": "code",
80+
"execution_count": null,
81+
"metadata": {},
82+
"outputs": [],
83+
"source": [
84+
"class Solution:\n",
85+
" def sortArray(self, nums: List[int]) -> List[int]:\n",
86+
" if nums is None: return None\n",
87+
" n = len(nums)\n",
88+
" for i in range(1,n):\n",
89+
" j = i\n",
90+
" while j > 0 and nums[j-1] > nums[j]:\n",
91+
" nums[j-1],nums[j] = nums[j],nums[j-1]\n",
92+
" j -= 1\n",
93+
" return nums"
94+
]
95+
},
96+
{
97+
"cell_type": "markdown",
98+
"metadata": {},
99+
"source": [
100+
"归并排序:O(nlogn的时间复杂度),O(n)的空间复杂度"
101+
]
102+
},
103+
{
104+
"cell_type": "code",
105+
"execution_count": null,
106+
"metadata": {},
107+
"outputs": [],
108+
"source": [
109+
"class Solution:\n",
110+
" def sortArray(self, nums: List[int]) -> List[int]:\n",
111+
" def merge_sort(nums):\n",
112+
" if len(nums) <= 1:\n",
113+
" return nums\n",
114+
" mid = len(nums) // 2\n",
115+
" # 分\n",
116+
" left = merge_sort(nums[:mid])\n",
117+
" right = merge_sort(nums[mid:])\n",
118+
" # 合并\n",
119+
" return merge(left, right)\n",
120+
"\n",
121+
"\n",
122+
" def merge(left, right):\n",
123+
" res = []\n",
124+
" i = 0\n",
125+
" j = 0\n",
126+
" while i < len(left) and j < len(right):\n",
127+
" if left[i] <= right[j]:\n",
128+
" res.append(left[i])\n",
129+
" i += 1\n",
130+
" else:\n",
131+
" res.append(right[j])\n",
132+
" j += 1\n",
133+
" res += left[i:]\n",
134+
" res += right[j:]\n",
135+
" return res\n",
136+
" return merge_sort(nums)"
137+
]
138+
},
139+
{
140+
"cell_type": "markdown",
141+
"metadata": {},
142+
"source": [
143+
"快排:不稳定排序,内排序,时间复杂度度O(nlogn) 最差 O(n^2)\n",
144+
" \n",
145+
"快速排序 的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。\n",
146+
"\n",
147+
"6.1 算法描述\n",
148+
"\n",
149+
"快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:\n",
150+
"步骤1:从数列中挑出一个元素,称为 “基准”(pivot );\n",
151+
"步骤2:重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;\n",
152+
"步骤3:递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。\n",
153+
"\n",
154+
"时间复杂度:最好情况O(n * logn)——Partition函数每次恰好能均分序列,其递归树的深度就为.log2n.+1(.x.表示不大于x的最大整数),即仅需递归log2n次; 最坏情况O(n^2),每次划分只能将序列分为一个元素与其他元素两部分,这时的快速排序退化为冒泡排序,如果用数画出来,得到的将会是一棵单斜树,也就是说所有所有的节点只有左(右)节点的树;平均时间复杂度O(n*logn)"
155+
]
156+
},
157+
{
158+
"cell_type": "code",
159+
"execution_count": null,
160+
"metadata": {},
161+
"outputs": [],
162+
"source": [
163+
"def quick_sort(nums):\n",
164+
" n = len(nums)\n",
165+
"\n",
166+
" def quick(left, right):\n",
167+
" if left >= right:#递归到左和右一样,直接退出\n",
168+
" return nums\n",
169+
" pivot = left\n",
170+
" i = left\n",
171+
" j = right\n",
172+
" while i < j:\n",
173+
" while i < j and nums[j] > nums[pivot]:#从右向左找第一个小于x的数\n",
174+
" j -= 1\n",
175+
" while i < j and nums[i] <= nums[pivot]:#从左向右找第一个大于x的数\n",
176+
" i += 1\n",
177+
" nums[i], nums[j] = nums[j], nums[i]#两者交换\n",
178+
" nums[pivot], nums[j] = nums[j], nums[pivot]#把pivot放到停止的位置(之前小于pivot的数已经被挖走,此处是空的)\n",
179+
" quick(left, j - 1)\n",
180+
" quick(j + 1, right)\n",
181+
" return nums\n",
182+
"\n",
183+
" return quick(0, n - 1)"
184+
]
185+
},
186+
{
187+
"cell_type": "markdown",
188+
"metadata": {},
189+
"source": [
190+
"堆排序\n",
191+
"\n",
192+
"最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序,空间复杂度O(1)\n",
193+
"堆排序(Heapsort) 是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。\n",
194+
"\n",
195+
"7.1 算法描述\n",
196+
"步骤1:将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;\n",
197+
"步骤2:将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];\n",
198+
"步骤3:由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。\n",
199+
"\n",
200+
"a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;\n",
201+
"\n",
202+
"b.将堆顶元素与末尾元素交换,将最大元素\"\"到数组末端;\n",
203+
"\n",
204+
"c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。"
205+
]
206+
},
207+
{
208+
"cell_type": "markdown",
209+
"metadata": {},
210+
"source": [
211+
"步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。\n",
212+
"\n",
213+
"https://www.cnblogs.com/chengxiao/p/6129630.html\n",
214+
"该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:\n",
215+
"\n",
216+
"大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] \n",
217+
"\n",
218+
"小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] \n",
219+
"\n",
220+
"步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。\n",
221+
"a.假设给定无序序列结构如下\n",
222+
"2.此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点 arr.length/2-1=5/2-1=1,也就是下面的6结点),从左至右,从下至上进行调整。\n",
223+
"找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换。\n",
224+
"这时,交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6。\n",
225+
"此时,我们就将一个无需序列构造成了一个大顶堆。\n",
226+
"\n",
227+
"步骤二 将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。"
228+
]
229+
},
230+
{
231+
"cell_type": "code",
232+
"execution_count": null,
233+
"metadata": {},
234+
"outputs": [],
235+
"source": [
236+
"class Solution:\n",
237+
" def sortArray(self, nums: List[int]) -> List[int]:\n",
238+
" def max_heapify(heap, root, heap_len):\n",
239+
" #root是起点, heap_len代表着终点(不包括)\n",
240+
" p = root\n",
241+
" while p * 2 + 1 < heap_len:\n",
242+
" #左子一定在heap里面\n",
243+
" l, r = p * 2 + 1, p * 2 + 2\n",
244+
" #右子不在heap中或者右子值比左子要小\n",
245+
" if heap_len <= r or heap[r] < heap[l]:\n",
246+
" nex = l\n",
247+
" else:\n",
248+
" nex = r\n",
249+
" #换了值就要向下一层遍历\n",
250+
" if heap[p] < heap[nex]:\n",
251+
" heap[p], heap[nex] = heap[nex], heap[p]\n",
252+
" p = nex\n",
253+
" #没有必要遍历下去了,因为没有换值\n",
254+
" else:\n",
255+
" break\n",
256+
"\n",
257+
" def build_heap(heap):\n",
258+
" #从最后一个非叶子节点开始进行调整,构建一个大顶堆\n",
259+
" for i in range(len(heap)//2-1, -1, -1):\n",
260+
" max_heapify(heap, i, len(heap))\n",
261+
"\n",
262+
" def heap_sort(nums):\n",
263+
" #从最后一个非叶子节点开始进行调整,构建一个大顶堆\n",
264+
" build_heap(nums)\n",
265+
" #交换最后一个和第一个,把剩下的构建成大顶堆\n",
266+
" #之前构建大顶堆需要从非叶节点从后向前进行调整,是因为整个结构都不是大顶堆,现在只有根节点不满足条件,所以只要对根节点做max_heapify就行了\n",
267+
" for i in range(len(nums) - 1, 0, -1):\n",
268+
" nums[i], nums[0] = nums[0], nums[i]\n",
269+
" max_heapify(nums, 0, i)\n",
270+
"\n",
271+
" heap_sort(nums)\n",
272+
" return nums"
273+
]
274+
}
275+
],
276+
"metadata": {
277+
"kernelspec": {
278+
"display_name": "Python 3",
279+
"language": "python",
280+
"name": "python3"
281+
},
282+
"language_info": {
283+
"codemirror_mode": {
284+
"name": "ipython",
285+
"version": 3
286+
},
287+
"file_extension": ".py",
288+
"mimetype": "text/x-python",
289+
"name": "python",
290+
"nbconvert_exporter": "python",
291+
"pygments_lexer": "ipython3",
292+
"version": "3.7.0"
293+
}
294+
},
295+
"nbformat": 4,
296+
"nbformat_minor": 4
297+
}

0 commit comments

Comments
 (0)