目录
目录
写在最前面:
python有自带的排序函数,sort和sorted,非常方便,除特殊情况,直接用
常见的排序算法:
1. 冒泡排序
先从数组中找到最大值(或最小值)并放到数组最左端(或最右端),然后在剩下的数字中找到次大值(或次小值),以此类推,直到数组有序排列。
时间复杂度:O(n^2)
def BubbleSort(array):
length = len(array)
for i in range(length):
for j in range(length-i-1):
if array[j] > array[j+1]:
array[j], array[j+1] = array[j+1], array[j]
return array
2. 选择排序
假设长度为n的数组arr,要按照从小到大排序,那么先从n个数字中找到最小值min1,如果最小值min1的位置不在数组的最左端(也就是min1不等于arr[0]),则将最小值min1和arr[0]交换,接着在剩下的n-1个数字中找到最小值min2,如果最小值min2不等于arr[1],则交换这两个数字,依次类推,直到数组arr有序排列。
时间复杂度:O(n^2)
def SelectionSort(array):
length = len(array)
for i in range(length):
min_index = array.index(min(array[i:]))
if min_index != i:
array[i], array[min_index] = array[min_index], array[i]
return array
3. 插入排序
插入排序的基本思想就是将无序序列插入到有序序列中。
时间复杂度:O(n^2)
def InsertSort(array):
length = len(array)
for i in range(1, length):
if array[i] < array[i-1]:
for j in range(i, 0, -1):
if array[j]<array[j-1]:
array[j], array[j-1] = array[j-1], array[j]
return array
4. 桶排序
桶排序的思路:首先找到数组中的最大值,然后新建一个数组,bucket 此数组的长度是数组最大值+1,找到最大值后,开始遍历原数组,把原数组的数据加入bucket的下表中,bucket[i],每当有1个i bucket[i]的值就加一, 然后已经装入桶后, 遍历桶。
时间复杂度:O(n)
def BucketSort(array):
length = len(array)
max_n = max(array)
bucket = [0 for _ in range(max_n+1)]
for i in range(length):
bucket[array[i]] += 1
start = 0
for j in range(max_n+1):
if bucket[j]!=0:
array[start] = j
start += 1
return array
5. 快速排序
快排的思想:首先任意选取一个数据作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
时间复杂度:O(lNogN)
空间复杂度:O(logN)
def QuickSort(array, start, end):
if start < end:
index = Partition(array, start, end)
QuickSort(array, start, index-1)
QuickSort(array, index+1, end)
def Partition(array, start, end):
print(start, end)
small = start-1
base = array[end]
for i in range(start, end):
if array[i] < base:
small += 1
if small != i:
array[small], array[i] = array[i], array[small]
small+=1
array[small], array[end] = array[end], array[small]
return small
6. 归并排序
归并排序采用分而治之的原理:
一、将一个序列从中间位置分成两个序列;
二、在将这两个子序列按照第一步继续二分下去;
三、直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。
时间复杂度:O(lNogN)
空间复杂度:O(N)
def MergeSort(array):
length = len(array)
if length<=1:
return array
middle = length//2
left = MergeSort(array[:middle])
right = MergeSort(array[middle:])
return Merge(left, right)
def Merge(left, right):
result = []
i=j=0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i+=1
else:
result.append(right[j])
j+=1
result += left[i:]
result += right[j:]
return result
7. 堆排序
堆排序(Heap Sort)是利用堆进行排序的方法。其基本思想为:将待排序列构造成一个大顶堆,整个序列的最大值就是堆顶的根结点,将根节点的值和堆数组的末尾元素交换,此时末尾元素就是最大值,然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值,如此反复执行,最终得到一个有序序列。
时间复杂度:O(Nlog(N))
空间复杂度:O(1)
def swap(a, b): # 将a,b交换
temp = a
a = b
b = temp
return a,b
def sift_down(array, start, end):
"""
调整成大顶堆,初始堆时,从下往上;交换堆顶与堆尾后,从上往下调整
:param array: 列表的引用
:param start: 父结点
:param end: 结束的下标
:return: 无
"""
while True:
# 当列表第一个是以下标0开始,结点下标为i,左孩子则为2*i+1,右孩子下标则为2*i+2;
# 若下标以1开始,左孩子则为2*i,右孩子则为2*i+1
left_child = 2*start + 1 # 左孩子的结点下标
# 当结点的右孩子存在,且大于结点的左孩子时
if left_child > end:
break
if left_child+1 <= end and array[left_child+1] > array[left_child]:
left_child += 1
if array[left_child] > array[start]: # 当左右孩子的最大值大于父结点时,则交换
array[left_child], array[start] = swap(array[left_child], array[start])
start = left_child # 交换之后以交换子结点为根的堆可能不是大顶堆,需重新调整}
else: # 若父结点大于左右孩子,则退出循环
break
print(">>", array)
def heap_sort(array): # 堆排序
# 先初始化大顶堆
first = len(array)//2 -1 # 最后一个有孩子的节点(//表示取整的意思)
# 第一个结点的下标为0,很多博客&课本教材是从下标1开始,无所谓吧,你随意
for i in range(first, -1, -1): # 从最后一个有孩子的节点开始往上调整
print(array[i])
sift_down(array, i, len(array)-1) # 初始化大顶堆
print("初始化大顶堆结果:", array)
# 交换堆顶与堆尾
for head_end in range(len(array)-1, 0, -1): # start stop step
array[head_end], array[0] = swap(array[head_end], array[0]) # 交换堆顶与堆尾
sift_down(array, 0, head_end-1) # 堆长度减一(head_end-1),再从上往下调整成大顶堆
if __name__ == "__main__":
array = [16, 7, 3, 20, 17, 8]
print(array)
heap_sort(array)
print("堆排序最终结果:", array)
Leetcode
242 有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
return sorted(s)==sorted(t)
349 两个数组的交集
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]
示例 2:
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]
说明:
- 输出结果中的每个元素一定是唯一的。
- 我们可以不考虑输出结果的顺序。
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
if not nums1 or not nums2:
return []
nums1.sort()
nums2.sort()
len1 = len(nums1)
len2 = len(nums2)
result = []
while nums1 and nums2:
if nums1[0] == nums2[0]:
if not nums1[0] in result:
result.append(nums1[0])
nums1.pop(0)
nums2.pop(0)
elif nums1[0]>nums2[0]:
nums2.pop(0)
elif nums1[0] < nums2[0]:
nums1.pop(0)
return result
350 两个数组的交集 ||
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
示例 2:
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
说明:
- 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
- 我们可以不考虑输出结果的顺序。
进阶:
- 如果给定的数组已经排好序呢?你将如何优化你的算法?
- 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
- 如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1.sort()
nums2.sort()
result = []
if not nums1 or not nums2:
return []
len1 = len(nums1)
len2 = len(nums2)
while nums1 and nums2:
if nums1[0] == nums2[0]:
result.append(nums1[0])
nums1.pop(0)
nums2.pop(0)
elif nums1[0] > nums2[0]:
nums2.pop(0)
elif nums1[0] < nums2[0]:
nums1.pop(0)
return result
922 按奇偶排序数组 ||
给定一个非负整数数组 A
, A 中一半整数是奇数,一半整数是偶数。
对数组进行排序,以便当 A[i]
为奇数时,i
也是奇数;当 A[i]
为偶数时, i
也是偶数。
你可以返回任何满足上述条件的数组作为答案。
示例:
输入:[4,2,5,7]
输出:[4,5,2,7]
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
提示:
2 <= A.length <= 20000
A.length % 2 == 0
0 <= A[i] <= 1000
思路: 直接遍历
class Solution:
def sortArrayByParityII(self, A: List[int]) -> List[int]:
if not A:
return []
odd = 1
even = 0
length = len(A)
result = [None for _ in range(length)]
for i in range(length):
if A[i] & 1 == 0:
result[even] = A[i]
even += 2
else:
result[odd] = A[i]
odd += 2
return result
976 三角形的最大周长
给定由一些正数(代表长度)组成的数组 A
,返回由其中三个长度组成的、面积不为零的三角形的最大周长。
如果不能形成任何面积不为零的三角形,返回 0
。
示例 1:
输入:[2,1,2]
输出:5
示例 2:
输入:[1,2,1]
输出:0
示例 3:
输入:[3,2,3,4]
输出:10
示例 4:
输入:[3,6,2,3]
输出:8
提示:
3 <= A.length <= 10000
1 <= A[i] <= 10^6、
思路:排序检查后三个数
class Solution:
def largestPerimeter(self, A: List[int]) -> int:
A.sort()
length = len(A)
if length<3:
return 0
for i in range(length-1, 1,-1):
if A[i-1] + A[i-2] > A[i]:
return A[i-1]+A[i-2]+A[i]
return 0