[face_算法篇]:常見的二分、遞歸、選擇、插入、冒泡、快排、歸併

算法篇python

  • 遞歸:斐波那契

必須有結束條件算法

python默認層數998app

斐波那契數列規律:0,1,1,2,3,5,8……ide

臺階問題:走1,走2,n階有幾種方案:fib = lambda n:n if n <= 2 else fib(n-1) + fib(n-2)ui

臺階升級:走1,走2,走n: fib = lambda n:n if n<=2 else 2* fib(n-1)指針

def feibo(n):
   """計算幾個feibo數"""
  if  n ==1:return 0  
       if  n == 2: return 1
       return  feibo(n-1) + feibo(n-2)
  • 二分查找:必須是有序的 O(logn)

找到中間值,讓待找值與中間值比,而後去兩邊找,條件就是左邊的索引小於右邊code

def  second_select(li, vlue):
   low = 0
   high = len(li) -1
   while low <=high:
       mid = (low + high)//2
       if  li[mid] == vlue:
           return mid
       elif  li[mid] > vlue:
           high = mid -1
        elif li[mid] < vlue:
           low = mid +
    else:
       return "沒有該值"
  • 選擇排序On^2

分有序無序,每次都從無序裏獲取最小的值放到有序最後一位的後面,直到無序區爲空blog

def select_sort(li):
   for i in range(len(li)-1):
       min_tmp = i
       for j in range(i+1, len(li)):
           if li[j] < li[min_tmp]
          min_tmp = j
        if  min_tmp  != j:
           li[i], li[min_tmp] = li[min_tmp] ,li[i]
  • 插入排序 On^2

分有序和無序,先從無序開始選一個數,放入有序區,而後從無序區拿元素與有序區元素依次比較,若是小於有序區,就換位置,若是大就放在它後面,依次進行排序

def insert_sort(li):
   for  i in range(1, len(li)):   # 先拿到了0號元素,這裏時無序區開始拿
       tmp = li[i]   # 獲取到的第一個數
       j = i -1  # 爲有序區的索引
       while   j >=0 and  tmp < li[j]:
           li [j+1] = li[j]   # 換位置
           j = j -1     # 有序區繼續比較
        li[j+1] = tmp
  • 冒泡

從一個列表開始元素依次開始比較相鄰的數,若是後面的大於前面的,不作改變,指針向後移動,若是後面的數小於前面的,將他們的位置更換,依次到最後,就實現了最大的數字放在了最後,相似水泡冒上來遞歸

def  mao_sort(li):
   for i in range(len(li) -1):   # 趟數
       flag = False
       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 = True
        if  not flag:
           return
  • 快排On^2

找到中間值,將列表分爲兩部分,左邊的元素都比中間值小,右邊的元素都比中間值大,而後兩部分也這樣遞歸的運行

def  quick_sort(li, left,right):
if  left < right:
       mid = partition(li, left, right)
       quick_sort(li, left, mid-1)
       quick_sort(li, mid+1)
def  partition(li, 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[right] <= tmp:
           left+-=1
        li[right]= li[left]
   li[left] = tmp
   return left
  • 歸併O(nlogn)

經過不斷的分解無序列表,直到成一個元素時就有序了,最後分紅兩個有序的列表,而後將兩個有序列表進行歸併,一步步遞歸合成一個有序的大列表

歸併排序採用分而治之的原理:

1、將一個序列從中間位置分紅兩個序列;

 2、在將這兩個子序列按照第一步繼續二分下去;

 3、直到全部子序列的長度都爲1,也就是不能夠再二分截止。這時候再兩兩合併成一個有序序列便可。
def merge(li, low, mid, high):
   li_tmp = []
   i = low
   j = mid + 1
   while i <= mid and j <= high:
       if li[i] <= li[j]:
           li_tmp.append(li[i])
           i += 1
       else:
           li_tmp.append(li[j])
           j += 1
   while i <= mid:
       li_tmp.append(li[i])
       i += 1
   while j <= high:
       li_tmp.append(li[j])
       j += 1
   for i in range(len(li_tmp)):
       li[i+low] = li_tmp[i]

def _merge_sort(li, low, high):
   if low < high: # 2個元素及以上
       mid = (low + high) // 2
       _merge_sort(li, low, mid)
       _merge_sort(li, mid+1, high)
       #print(li[low:mid+1], li[mid+1:high+1])
       merge(li, low, mid, high)
       #print(li[low:high + 1])

# 兩個列表的寫法
def merge_two(li1, li2):
   li = []
   i = 0
   j = 0
   while i < len(li1) and j < len(li2):
       if li1[i] <= li2[j]:
           li.append(li1[i])
           i += 1
       else:
           li.append(li2[j])
           j += 1
   while i < len(li1):
       li.append(li1[i])
       i += 1
   while j < len(li2):
       li.append(li2[j])
       j += 1
   return li

[face_算法篇]:常見的二分、遞歸、選擇、插入、冒泡、快排、歸併

相關文章
相關標籤/搜索