3500 字算法刷題精華總結

第一週週報完整 pdf 版下載地址:

https://t.zsxq.com/rBMVzbM

第二週週報完整 pdf 下載地址:

https://t.zsxq.com/YJiiQz7

本週第三週週報請於星球內下載

上週星球活躍度官方數據如下,連續三週星球活躍度都很不錯,感謝星友們的參與,繼續努力+堅持。

Day 18:二分查找算法

Day 17 作業題

寫出幾種常見覆雜度對應的算法,星友們給出的答案都很準確,在這裏參考星友聶磊的答案:

時間複雜度:

常見操作:哈希查找數組取值常數加減乘除

: 二分查找

計算數組中所有元素和,最大,最小

歸併排序,堆排序,希爾排序,快速排序

² :冒泡,選擇排序

:三元方程暴力求解

:求解所有子集

:全排列問題。比如:給定字母串,每個字母必須使用,且一次組合中只能使用一次,求所有組合方式;另外還要經典的旅行商 TSP 問題

下面這幅圖太直觀了:

其中,複雜度爲: 是難解的問題,,²都是可以接受的解,, 的解是夢寐以求的。

Day 18 :二分查找

二分查找算法,binary search algorithm,也稱折半搜索算法對數搜索算法

它的使用前提:是一種在有序數組中查找某一特定元素的搜索算法。

請補全下面二分查找算法:

# 返回hkey在數組中的索引位置
def binary_search(arr, left, right, hkey):
    """
    arr:有序數組
    left:查找區間左側
    right:查找區間右側
    hkey:帶查找的關鍵碼
    備註:left, right 都包括在內,找不到返回 -1
  
    """
    #
    #
    #

Day 19 合併兩個有序序列

Day 18 作業總結

寫出二分查找算法

已知函數原型:

def binary_search(arr,left,right,hkey):
    pass

要求補全上述代碼

注意事項:

  1. (left+right) //2 ,更好寫法:left + (right-left)//2

  2. 迭代中,一定注意while判斷中等號問題

  3. 二分查找的代碼還是很容易寫出bug

迭代二分查找

代碼參考星友 Leven:

def binary_search(arr,left,right,hkey):
    while left <= right:
        mid = left + (right-left) // 2
  
        if arr[mid] == hkey:
            return mid
        elif arr[mid] > hkey: # 嚴格大於
            right = mid - 1 
        else: # 此處嚴格小於
            left = mid + 1  
            
    return -1 # 表示找不到
if __name__ == "__main__":
    sorted_list = [1,2,3,4,5,6,7,8]
    result = binary_search(sorted_list,0,7,4)
    print(result)

遞歸二分查找

def binary_search(arr,left,right,hkey):
    if len(arr) == 0:
        return -1
  
    if left > right:
        return -1
  
    mid = left + (right-left) // 2
 
    if arr[mid] == hkey:
        return mid
    elif arr[mid] < hkey: # 嚴格小於
        return binary_search(arr,mid+1,right,hkey) # 折半
    else:
        return binary_search(arr,left,mid-1,hkey)

if __name__ == "__main__":
    sorted_list = [1,2,3,4,5,6,7,8]
    result = binary_search(sorted_list,0,7,4)
    print(result)

更多演示動畫

能找到關鍵碼:

不能找到關鍵碼:

Day 19 作業題

合併兩個有序數組 left 和 right:

def merge(left,right):
  #補全代碼
  #
  return temp

思路可參考示意圖:

Day 20 歸併排序算法

Day 19 合併兩個有序數組作業總結

合併兩個有序數組

利用兩個數組原本已經有序的特點:

def merge(left, right):
    i = 0
    j = 0
    temp = []
    while i <= len(left) - 1 and j <= len(right) - 1:
        if left[i] <= right[j]:
            temp.append(left[i])
            i += 1
        else:
            temp.append(right[j])
            j += 1
    temp += left[i:] + right[j:]
    return temp

print(merge([1,3,4],[2,3,3])) 

思路可參考示意圖:

Day20 寫出歸併排序算法

歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然後遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。

歸併排序算法的核心正是 Day 19 的合併兩個有序數組,補全如下代碼:

def merge_sort(lst):
    #
    #
    #
    return lst_sorted

歸併排序兩階段:

先分,直到長度1,然後再合:

歸併排序的詳細講解,可參考:https://www.programiz.com/dsa/merge-sort

Day 21 21 天刷題總結

很多星友都一直堅持到現在,21 天整,都說 21 天養成一個習慣,據此推斷,相信你們養成了刷題的習慣~~

下面我們先總結下 Day 20 的歸併排序作業題

Day 20 寫出歸併排序算法

歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然後遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。

# Python program for implementation of MergeSort 
def mergeSort(arr): 
    if len(arr) >1: 
        mid = len(arr)//2 # Finding the mid of the array 
        L = arr[:mid] # Dividing the array elements  
        R = arr[mid:] # into 2 halves 
  
        mergeSort(L) # Sorting the first half 
        mergeSort(R) # Sorting the second half 
  
        i = j = k = 0
          
        # Copy data to temp arrays L[] and R[] 
        while i < len(L) and j < len(R): 
            if L[i] < R[j]: 
                arr[k] = L[i] 
                i+= 1
            else: 
                arr[k] = R[j] 
                j+= 1
            k+= 1
          
        # Checking if any element was left 
        while i < len(L): 
            arr[k] = L[i] 
            i+= 1
            k+= 1
          
        while j < len(R): 
            arr[k] = R[j] 
            j+= 1
            k+= 1

驗證調用:

  
# Code to print the list 
def printList(arr): 
    for i in range(len(arr)):         
        print(arr[i], end =" ") 
    print() 
  
# driver code to test the above code 
if __name__ == '__main__': 
    arr = [12, 11, 13, 5, 6, 7]  
    print ("Given array is", end ="\n")  
    printList(arr) 
    mergeSort(arr) 
    print("Sorted array is: ", end ="\n") 
    printList(arr) 

思路可參考示意圖:

歸併排序的詳細講解,可參考:

https://www.programiz.com/dsa/merge-sort

Day 21 打卡

與這麼多星友一起刷題的這21天,請寫出你的心得體會,另外若你有什麼建議,歡迎也反饋一下。

Day 22 21 天刷題總結

很多星友都一直堅持到現在,21 天整,都說 21 天養成一個習慣,據此推斷,相信你們養成了刷題的習慣~~

下面我們看看星友們的刷題心得總結:

Day 21 天刷題總結


節選幾位星友21天刷題總結

還有更多星友的21天打卡總結,在此不一一列舉。

總之,看到大家有收穫,所以與大家一起堅持下去,大的指導方向不變。按照有些星友的反饋,會增加進階題目,同時週末會增加算法學習經驗分享等。

Day 22 打卡:使用遞歸以相反的順序打印字符串

前面的歸併排序,用到遞歸。

遞歸是計算機科學中的一個重要概念。它是計算機算法的基礎。接下來幾天,我們詳細的探討遞歸的原理,如何更高效的使用遞歸解決實際問題。

今天先從一個基礎題目體會遞歸的原理:使用遞歸以相反的順序打印字符串。

def reverse_print(s):
    #
    #補充完整
    #

謝謝大家!

Day 23:

Day 22:使用遞歸以相反的順序打印字符串

先看題目的求解方法。

遞歸方法一:

def reverse_print(s):
    if len(s) <= 1:
        return s 
    return reverse_print(s[1:]) + s[0] 

使用遞歸,往往代碼會很簡潔,但若不熟悉遞歸,理解起來就會相對困難。

下面藉助示意圖解釋以上遞歸過程:

假如這樣調用 reverse_print

reverse_print('abcdef')

那麼遞歸過程時,函數reverse_print會不斷入棧,示意圖如下:

此時棧頂爲入參 f 的函數,位於示意圖的最底部。

因爲它滿足了遞歸返回條件len(s) <= 1,所以棧頂函數首先出棧,並返回值 f,下一個即將出棧的爲入參ef的函數,其返回值爲fe,如下所示:

依次出棧:

最後一個留在棧的reverse_print,即將返回我們想要的結果:

它也出棧後,我們變得到結果 fedcba

以上就是使用遞歸反轉打印字符的方法。

其他使用遞歸反轉字符串的方法,大家多看看其他星友的解法即可。

Day 23:使用遞歸:兩兩交換鏈表中的節點

給定鏈表,交換每兩個相鄰節點並返回其頭節點。

例如,對於列表 1-> 2 -> 3 -> 4,我們應當返回新列表 2 -> 1 -> 4 -> 3 的頭節點。

請補充下面函數:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def swapPairs(self, head: ListNode):
        pass # 請補充

Day 24:遞歸生成楊輝三角

先來總結昨天的作業

Day 23:遞歸兩兩交換鏈表中的節點

給定鏈表,交換每兩個相鄰節點並返回其頭節點。

例如,對於列表 1-> 2 -> 3 -> 4,我們應當返回新列表 2 -> 1 -> 4 -> 3 的頭節點。

請補充下面函數:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def swapPairs(self, head: ListNode):
        pass # 請補充

使用遞歸的解題思路,見下面示意圖:

兌現爲代碼如下:

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head
        tmp = head.next
        r = self.swapPairs(tmp.next)
        tmp.next = head
        head.next = r
        return tmp

連上完整的驗證代碼:

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head
        tmp = head.next
        r = self.swapPairs(tmp.next)
        tmp.next = head
        head.next = r
        return tmp


if __name__ == "__main__":
    # create ListNode from list a
    a = [1, 2, 3, 4, 5]
    head = ListNode(a[0])
    tmp = head
    for i in range(1, len(a)):
        node = ListNode(a[i])
        tmp.next = node
        tmp = tmp.next
    # swap pairs
    snode = Solution().swapPairs(head)
    # check result
    tmp = snode
    while tmp:
        print(tmp.val)
        tmp = tmp.next

遞歸使用的訣竅:

每當遞歸函數調用自身時,它都會將給定的問題拆解爲子問題。遞歸調用繼續進行,直到到子問題無需進一步遞歸就可以解決的地步。

剛剛接觸遞歸,使用起來會比較彆扭,大家不妨結合昨天的遞歸調用棧,再多練習幾道遞歸題目,相信會越來越熟練。

Day 24:遞歸生成楊輝三角

給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。

請補全下面代碼:

class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        pass

如果你想從零學習算法,不妨加入下面星球,現在是最划算的時候,還提供專門的星友微信交流社羣,每天在星球裏記錄自己的學習過程,學習其他星友的解題分析思路。打卡 300 天退換除平臺收取的其他所有費用。

長按二維碼,加入我的星球

若有幫助,點個在看
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章