python算法题排序_python-数据结构与算法- 面试常考排序算法题-快排-冒泡-堆排-二分-选择等...
算法可視化網站推薦---->visualgo
0.面試題中的排序算法
一些排序算法可能在工作中用的會比較少,但是面試卻是不得不面對的問題。算法有助于提高我們對數據結構的理解以及提高自己的邏輯能力,沒事刷刷真的不錯。
1.快排
面試最推薦而且也是寫的最多的
快排的思路是分而治之,相當于我每次去將一個數歸為,直到所有的數都歸為了,那么這個排序也就成功了。
快排第一種思路:(這個思路參考下,不要寫)
平均時間復雜度
最好時間復雜度
最壞時間復雜度
空間復雜度
排序方式
O(nlogn)
O(nlogn)
O(n2)
O(nlogn)
in-place
import random
def quickSort(nums): # 這種寫法的平均空間復雜度為 O(nlogn),時間復雜度為O(nlogn)
if len(nums) <= 1:
return nums
mid = nums[0] # 基準值
left = [nums[i] for i in range(1, len(nums)) if nums[i] < mid]
right = [nums[i] for i in range(1, len(nums)) if nums[i] >= mid]
return quickSort(left) + [mid] + quickSort(right)
li = list(range(100))
random.shuffle(li)
print(li)
print(quickSort(li))
這個利用到了遞歸,分而治之,但是這個算法的空間復雜度較高,有可以優化的點。在做算法題的時候,對于列表字典這些可變數據結構,一定要明白如何去利用這些數據結構本身的內存而不是再去開辟很多新的內存。
快排第二種思路:
平均時間復雜度
最好時間復雜度
最壞時間復雜度
空間復雜度
排序方式
O(nlogn)
O(nlogn)
O(n2)
O(log)
in-place
import random
class Solution(object):
"""
快排
時間復雜度為O(nlogn),最差情況為O(n2)
空間復雜度為O(logn)
"""
def partition(self, li: list, left, right):
tmp = li[left]
while left < right:
while left < right and li[right] >= tmp:
right -= 1
li[left] = li[right]
while left < right and li[left] <= tmp:
left += 1
li[right] = li[left]
li[left] = tmp
return left
def quick_sort(self, li, left, right):
if left < right:
mid = self.partition(li, left, right)
self.quick_sort(li, left, mid - 1)
self.quick_sort(li, mid + 1, right)
li = list(range(100))
random.shuffle(li)
print(li)
solution = Solution()
print(solution.quick_sort(li, 0, len(li) - 1))
print(li)
與第一種方法不同的點就是在于對空間的利用,利用了li本身的內存空間。
寫在同一個函數里
如何把他們寫在同一個函數里并且有一個new idea,在找到兩邊各一個不屬于各自位置的值后,進行交換。
def quick_sort(li, start, end):
if start >= end:
return
left, right = start, end
tmp = li[left]
while left < right:
# 設置一個基準點
while left < right:
while left < right and li[right] >= tmp: # 至少要一個等號,不然會出現死循環
right -= 1
li[left] = li[right]
while left < right and li[left] <= tmp: # 因為如果沒有一邊有等號,當列表中有兩個相同值的時候,就無法跳出循環
left += 1
li[right] = li[left]
li[left] = tmp
quick_sort(li, start, left - 1)
quick_sort(li, left + 1, end)
if __name__ == '__main__':
import random
li = list(range(100))
li.append(55)
random.shuffle(li)
print(li)
print(quick_sort(li, 0, 99))
print(li)
順便把參數數量也降低一下:
def quick_sort(li):
def _quick_sort(li, start, end):
if start >= end:
return
left, right = start, end
tmp = li[left]
while left < right:
# 設置一個基準點
while left < right:
while left < right and li[right] >= tmp: # 至少要一個等號,不然會出現死循環
right -= 1
li[left] = li[right]
while left < right and li[left] <= tmp: # 因為如果沒有一邊有等號,當列表中有兩個相同值的時候,就無法跳出循環
left += 1
li[right] = li[left]
li[left] = tmp
_quick_sort(li, start, left - 1)
_quick_sort(li, left + 1, end)
_quick_sort(li, 0, len(li)-1)
2.冒泡排序
平均時間復雜度
最好時間復雜度
最壞時間復雜度
空間復雜度
排序方式
O(n2)
O(n)
O(n2)
O(1)
in-place
理解的關鍵點在于左半部分是有序區。
冒泡作為最簡單的排序算法之一,面試的時候萬不得已(其他的都記不住了),還是不要寫。寫個快排能好多了。
import random
class Solution(object):
"""
冒泡排序
"""
@staticmethod
def bubble_sort(li):
for i in range(len(li) - 1): # 交換的次數
flag = True # flag的作用是當這個序列就是一個升序(這邊排的是升序),那么久可以降低時間復雜度到O(n)
for j in range(len(li) - i - 1): # 剩余需要交換的元素
if li[j] > li[j + 1]:
li[j], li[j + 1] = li[j + 1], li[j]
flag = False
if flag:
return li
return li
li = list(range(100))
random.shuffle(li)
print(li)
solution = Solution()
solution.bubble_sort(li)
print(li)
3.選擇排序
平均時間復雜度
最好時間復雜度
最壞時間復雜度
空間復雜度
排序方式
O(n2)
O(n2)
O(n2)
O(1)
in-place
選擇排序主要需要注意點是左邊部分是有序區。
也不推薦寫,時間復雜度高,效率低,太簡單了。
import random
class Solution(object):
"""
選擇排序
"""
def select_sort(self, li):
for i in range(len(li) - 1):
min_pos = i
for j in range(i+1, len(li)): # 左部分是有序區
if li[min_pos] > li[j]:
min_pos = j
li[i], li[min_pos] = li[min_pos], li[i]
return li
li = list(range(100))
random.shuffle(li)
print(Solution().select_sort(li))
4.插入排序
插入排序如同打撲克一樣,每次將后面的牌插到前面已經排好序的牌中。使得左半部分為有序區域。
平均時間復雜度
最好時間復雜度
最壞時間復雜度
空間復雜度
排序方式
O(n2)
O(n2)
O(n2)
O(1)
in-place
import random
def insert_sort(li):
for i in range(1, len(li)):
# i 表示趟數 還表示摸到牌的位置
j = i - 1 # 取到摸到牌的前一張,也就是有序位置的最后一張牌
tmp = li[i]
while j >= 0 and li[j] > tmp:
# 兩個終止條件: 1. j==-1 2. j位置的值小于等于tmp
li[j + 1] = li[j]
j -= 1
li[j + 1] = tmp
li = list(range(10000))
random.shuffle(li)
insert_sort(li)
print(li)
5.堆排序(Heap Sort)
import random
def sift(li, low, high):
"""
堆調整程序
:param li:
:param low:
:param high:
:return:
"""
tmp = li[low]
i = low
j = 2 * i + 1
while j <= high: # 第一個退出條件:j不存在
if j + 1 <= high and li[j + 1] > li[j]: # 如果右孩子存在并且右孩子比左孩子大
j += 1 # j指向右孩子
if li[j] > tmp:
li[i] = li[j]
i = j
j = 2 * i + 1
else: # 第二個退出條件:j位置的值比tmp小
break
li[i] = tmp
def heap_sort(li):
# 1. 建堆
n = len(li)
for i in range(n // 2 - 1, -1, -1): # i表示遍歷的low
sift(li, i, n - 1) # low:i high:統一寫成最后一個位置對正確性沒有影響
# 2. 挨個出數:退休 棋子 調整
for i in range(n - 1, 0, -1): # i 表示當前位置堆的high
li[i], li[0] = li[0], li[i]
sift(li, 0, i - 1)
# print(li)
li = list(range(100000))
random.shuffle(li)
heap_sort(li)
print(li)
6.二分查找
二分查找非常簡單,是建立在列表有序的情況下,利用二分法不斷逼近目標值的。
def binary_search(li, target):
left = 0
right = len(li) - 1
while left <= right:
mid = (right - left) // 2 # 取一個中間值
if target > li[mid]:
left = mid + 1 # 如果比目標值比中位值還要大,調整右邊界指針
elif target < li[mid]:
right = mid - 1 # 如果比目標值比中位值要小,調整左邊界指針
else:
return mid
return -1
算法的穩定性
選擇排序、快速排序、希爾排序、堆排序不是穩定的排序算法,而冒泡排序、插入排序、歸并排序和基數排序是穩定的排序算法
總結
以上是生活随笔為你收集整理的python算法题排序_python-数据结构与算法- 面试常考排序算法题-快排-冒泡-堆排-二分-选择等...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【LeetCode笔记】142. 环形链
- 下一篇: websocket python爬虫_p