【python 中级】 算法 题目记录
本文章记录了有关 python 数据处理 题目 和 排序 查找 案例 的汇总。
# 【python 中级】 算法 题目记录
*python 技术栏*
本文章记录了有关 python 数据处理 题目 和 排序 查找 案例 的汇总。
## 目录
[TOC]

## 排序操作
### 冒泡排序
冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

```
def sort(arr: list[int]):
# 在冒泡排序中 每一次循环都会将一个数值放到合适的位置
# 例如 3 1 2 0 第一次冒泡之后 结果是 1 2 0 3
# 因此列表中有几个数值 就需要有几次冒泡
for index in range(0, len(arr)):
# 在每次的冒泡中 我们的任务其实就是将相邻的两个元素两两比较
for i in range(0, len(arr) - index - 1):
# 最终我们可以将最小或最大的放到前面
if arr[i] > arr[i + 1]:
arr[i], arr[i + 1] = arr[i + 1], arr[i]
print(f"第{index + 1}次冒泡结果 = {arr}")
if __name__ == '__main__':
d = [3, 1, 2, 0]
sort(d)
print(d)
```
### 选择排序
选择排序算法的工作原理是首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

```
def sort(arr: list[int]):
for index in range(0, len(arr)):
# 获取到当前已排序的数据中 最大的数值
max_num = arr[index]
# 使用循环 将最大数值后面未排序的值进行依次比较,将比 max 更小的值与 max 位置互换
# 因为小的要在前面 所以 max 变为更小的
for i in range(index + 1, len(arr)):
if arr[i] < max_num:
# 说明 arr[i] 比 max 更适合前面的位置 在这里进行交换位置
arr[index], arr[i] = arr[i], arr[index]
# 不要忘记更新这个值
max_num = arr[index]
print(f"第{index + 1}次选择,已排序位置为{index}:结果 = {arr}")
if __name__ == '__main__':
d = [3, 1, 2, 0]
sort(d)
print(d)
```
### 插入排序
插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到`O(1)`的额外空间的排序),因此它是稳定的。

```
def sort(arr: list[int]):
# 第一层循环其实就是标记 标记被排好序的元素
for index in range(1, len(arr)):
# 在这个循环中 我们只需要找到当前元素 并将下一个元素在已排序范围中找到合适的插入位置
for i in range(index, 0, -1):
# 在这个循环中 我们需要找到当前元素在当前以及前面所有元素的最佳位置
now_num = arr[i]
# 在这里进行比较 如果 now_num 的值更大 则需要将 now_num 值与已排序的值进行位置互换 直到找到合适的位置
if now_num < arr[i - 1]:
# 需要换位置
arr[i - 1], arr[i] = arr[i], arr[i - 1]
else:
# 代表找到合适位置了 前面不需要继续搜索了 直接结束
break
print(f"第{index}次插入,已排序位置为{index}:结果 = {arr}")
if __name__ == '__main__':
d = [3, 1, 2, 0, -1024]
sort(d)
print(d)
```
### 快速排序
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
> 它的步骤如下
① 从数列中挑出一个元素,称为 “基准”(pivot);
② 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
③ 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

```
def sort(arr: list[int]):
if len(arr) <= 1:
# 代表不需要排序了
return
elif len(arr) == 2:
# 直接交换下位置就行
if arr[0] > arr[1]:
arr[0], arr[1] = arr[1], arr[0]
print(f"最终排序:{arr}")
return
# 快速排序有两个步骤 一个是分区 一个是合并
# 分区的操作就是将比基准值小的区域和比基准值大的区域划分开 下面就是分区操作
pivot = arr[0]
# 使用循环创建两个列表 分别是比基准值小的和比基准值大的
l, r = [], []
for n in arr:
if n < pivot:
l.append(n)
else:
r.append(n)
print(f"基准值{pivot},待排序 = {l}, and {r}")
# 然后我们再让两个列表进行快速排序
sort(l)
sort(r)
# 写回结果
arr.clear()
arr.extend(l + r)
if __name__ == '__main__':
d = [3, 1, 2, 0, -1024]
sort(d)
print(d)
```
### 归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

```
# 用来存储临时结果!
r = []
def sort_fun(arr: list[int], low: int, high: int):
if low >= high:
# 代表排序结束了
return
# 获取到基准值索引
midIndex = low + ((high - low) >> 1)
# 排序 将左右部分排序
sort_fun(arr, low, midIndex)
sort_fun(arr, midIndex + 1, high)
print(f"排序之后 = {arr}")
# 准备两个标
l_index, r_index = low, midIndex + 1
r.clear()
# 开始进行合并 合并的逻辑是 l_index r_index 两个指针的值依次对比 按照大小顺序依次追加数据并移动指针
while l_index <= midIndex and r_index <= high:
# 将更小的追加到新的数组中
if arr[l_index] < arr[r_index]:
r.append(arr[l_index])
l_index += 1
else:
r.append(arr[r_index])
r_index += 1
# 将剩余的追加下
while l_index <= midIndex:
r.append(arr[l_index])
l_index += 1
while r_index <= high:
r.append(arr[r_index])
r_index += 1
# 将操作结束的结果写到 arr 里
l_index = low
for n in r:
arr[l_index] = n
l_index += 1
if l_index >= len(arr):
break
print(f"合并之后 = {arr}")
def sort(arr: list[int]):
sort_fun(arr, 0, len(arr) - 1)
if __name__ == '__main__':
d = [3, 1, 2, 0, -1024]
sort(d)
print(d)
```
## 查找操作
### 二分查找
```
def search(nums: list[int], target: int) -> int:
# 准备两个指针 代表查找的区间
l, r = 0, len(nums) - 1
while l <= r:
# 获取到当前中间值
midIndex = (l + r) // 2
midValue = nums[midIndex]
# 开始比较
if target < midValue:
# 舍弃右区间
r = midIndex - 1
elif target > midValue:
# 舍弃左区间
l = midIndex + 1
else:
# 区间中只剩下了一个元素 左右边界都指向这个数值了 就代表存在
return midIndex
# 如果区间的边界相互越过 说明没查找到元素
return -1
if __name__ == '__main__':
d = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1024]
print(search(d, 2))
print(search(d, 9))
```
------
***操作记录***
作者:[python](https://www.lingyuzhao.top//index.html?search=33 "python")
操作时间:2024-07-04 14:10:30 星期四
事件描述备注:保存/发布
中国 天津
[](如果不需要此记录可以手动删除,每次保存都会自动的追加记录)