Task 03:數(shù)組排序(day 1)

Task 03: 數(shù)組排序

數(shù)組排序第一天打卡,附上學(xué)習(xí)鏈接

1 學(xué)習(xí)內(nèi)容

1.1 冒泡排序(Bubble Sort)

冒泡排序法通過相鄰元素之間的比較與交換,使值越小的元素位置越往前,值越大的元素越往后,類比水底的氣泡向上冒的形態(tài)。

算法步驟:

  • (1)將序列中第1和2個元素進行比較,若前者大于后者,則交換位置,否則不交換;

  • (2)依次類推,直到第n-1和n個元素比較交換為止。一趟排序下來,最大的元素就會位于序列的第n個位置上;

  • (3)此后,對前n-1個元素同樣操作,將n-1個元素中值最大的放置在n-1的位置上;

  • (4)重復(fù),直至某一趟排序過程中不出現(xiàn)元素交換位置的動作,排序結(jié)束。

算法分析:

  • 最好的情況是,初始時序列呈升序狀態(tài),只需要n-1次元素之間的比較,并且無移動,可結(jié)束排序。此時,算法時間復(fù)雜度為O(n);

  • 最差的情況是,初始時序列是逆序狀態(tài)/最小值在尾,則需要n-1趟排序,總共進行n(n-1)/2次比較。因此,算法平均時間復(fù)雜度為O(n2);

  • 冒泡排序,需要移動次數(shù)較多,時間效率最低。適合于數(shù)據(jù)量較小/初始狀態(tài)基本有序的情況;

  • 元素的比較交換是在相鄰元素之間進行,不會該表值相同元素的相對位置,因此冒泡排序是一種穩(wěn)定排序法。

代碼實現(xiàn):

def bubbleSort(arr):
    for i in range(len(arr)):
        for j in range(len(arr)-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr
1.2 選擇排序(Selection Sort)

選擇排序在每一趟排序中,從剩下未排序元素中選擇一個最小的元素,與未排好序的元素最前面的那個元素交換位置。

算法步驟:

  • (1)設(shè)置整型變量i,作為排序次數(shù)的計算,也作為第i趟排序時,未排序的元素的第1個元素的位置;

  • (2)設(shè)置整型變量min_i,記錄未排序的n-i+1個元素中值最小元素的位置;

  • (3)每一趟排序開始,先令min_i = i(即暫定第i個元素為最小值,之后比較交換);

  • (4)第i趟排序比較結(jié)束時,其中真正的值最小元素為下標(biāo)min_i對應(yīng)的元素。此時,若min_i == i時,則不用進行交換。

算法分析:

  • n個元素的序列,選擇排序需要n-1趟;

  • 原始序列升序,移動次數(shù)最少,為0次;原始序列逆序,移動次數(shù)最多,為3(n-1)次【3是交換arr[i]和arr[min_i]的執(zhí)行次數(shù)】;

  • 無論序列中元素的初始排列狀態(tài)如何,第i趟排序要找出值最小元素都需要進行n-i次元素之間的比較。因此,整個排序過程需要進行的元素之間的比較次數(shù)都相同,為n(n-1)/2次,算法的時間復(fù)雜度為O(n2);

  • 由于值最小元素與未排好序的元素中第1個元素的交換動作是在不相鄰的元素之間進行的,因此很有可能會改變值相同元素的前后位置,因此選擇排序法是一種不穩(wěn)定的排序方法。

代碼實現(xiàn):

def selectionSort(arr):
    for i in range(len(arr) - 1):
        min_i = i
        for j in range(i+1, len(arr)):
            if arr[j] < arr[min_i]:
                min_i = j
        if i != min_i:
            arr[i], arr[min_i] = arr[min_i], arr[i]
    return arr
1.3 插入排序(Insertion Sort)

將整個序列切分為兩部分:前i-1個元素是有序序列,后n-i+1個元素是無序序列。每一次排序,將無序序列的首元素,在有序序列中找到相應(yīng)的位置并插入。

算法步驟:

  • (1)將第一個元素作為一個有序序列,將2~n-1個元素作為無序序列;

  • (2)從頭至尾一次掃描無序序列,將掃描到的每個元素插入到有序序列的適當(dāng)位置上。

算法分析:

  • 有n個元素的序列,插入排序方法一共要進行n-1趟排序;

  • 對于插入排序算法,整個排序過程只需要一個輔助空間tmp;

  • 當(dāng)原始序列升序,對應(yīng)的每個i值只進行一次元素之間的比較,因而總的比較次數(shù)最少,為n-1,且不需要移動元素(記錄);

  • 當(dāng)原始序列逆序,則對應(yīng)的每個i值都要進行i-1次元素之間的比較,總的比較次數(shù)最多,為n(n-1)/2;

  • 當(dāng)原始序列隨機,且參加排列的序列中元素可能出現(xiàn)的各站排列的概率相同,則取平均值作為比較次數(shù),約為n2/4,即算法的時間復(fù)雜度為O(n2);

  • 插入排序算法屬于穩(wěn)定性排序方法。

代碼實現(xiàn):

def insertionSort(arr):
    for i in range(1, len(arr)):
        tmp = arr[i]
        j = i
        while j > 0 and arr[j-1] > tmp:
            arr[j] = arr[j-1]
            j -= 1
        arr[j] = tmp
    return arr

2 練習(xí)題目

2.1 劍指Offer 45、把數(shù)組排成最小的數(shù) **

題目描述:輸入一個非負(fù)整數(shù)數(shù)組,將所有數(shù)字拼接起來排成一個數(shù),打印出拼接出的所有數(shù)字中最小的一個。 樣例1:輸入為[10, 2],輸出為"102"; 樣例2:輸入為[3, 30, 34, 5, 9],輸出為“3033459”。

解題思路:排序判斷規(guī)則為,如果x+y > y+x,則x應(yīng)該在y的左邊,反之亦然。

class Solution:
    def minNumber(self, nums: List[int]) -> str:
        def quick_sort(left, right):
            if left >= right:
                return
            i, j = left, right
            while i < j:
                while strs[j] + strs[left] >= strs[left] + strs[j] and i < j:
                    j -= 1
                while strs[i] + strs[left] <= strs[left] + strs[i] and i < j:
                    i += 1
                strs[i], strs[left] = strs[left], strs[i]
                quick_sort(left, i-1)
                quick_sort(i+1, right)
                
        strs = [str(num) for num in nums]
        quick_sort(0, len(strs) - 1)
        return ''.join(strs)
class Solution:
    def minNumber(self, nums: List[int]) -> str:
        def sort_rule(x, y):
            a, b = x + y, y + x
            if a > b: return 1
            elif a < b: return -1
            else: return 0
        
        strs = [str(num) for num in nums]
        strs.sort(key = functools.cmp_to_key(sort_rule))  # amazing
        return ''.join(strs)
2.2 0283 移動零 *

題目描述:給定一個數(shù)組nums,編寫一個函數(shù)將所有0移動到數(shù)組的末尾,同時保持非零元素的相對順序。 樣例1:輸入為[0, 1, 0, 3, 12],輸出為[1, 3, 12, 0, 0]。

解題思路:對0計數(shù),刪除0,并在末尾添加滿足數(shù)量的0。

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n = nums.count(0)

        for i in range(n):
            nums.remove(0)
        
        nums.extend([0] * n)

神奇的思路之雙指針,哈哈哈哈。

左指針指向當(dāng)前已經(jīng)處理好的序列的尾部,右指針指向待處理序列的頭部。右指針不斷向右移動,每次右指針指向非零數(shù),則將左右指針對應(yīng)的數(shù)交換,同時左指針右移。

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        left = right = 0
        while right < n:
            if nums[right] != 0:
                nums[left], nums[right] = nums[right], nums[left]
                left += 1
            right += 1
2.3 0912 排序數(shù)組 **

題目描述:將一個整數(shù)數(shù)組nums,實現(xiàn)升序排列。 樣例1:輸入為nums=[5, 2, 3, 1],輸出為[1, 2, 3, 5]; 樣例2:輸入為nums=[5, 1, 1, 2, 0, 0],輸出為[0, 0, 1, 1, 2, 5]。

解題思路:用上述三種方法排序。

hahahaha,都超時了,偷懶用個list內(nèi)置函數(shù)吧~~

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        nums.sort()
        return nums

day2打卡: day2鏈接
day3打卡: day3鏈接
day4打卡: day4鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容