【Python 算法零基礎 4.排序 ④ 計數排序】

目錄

一、引言

二、算法思想

三、算法分析

1.時間復雜度

2.空間復雜度

3.算法的優缺點

Ⅰ、算法的優點

Ⅱ、算法的缺點

四、實戰練習

75. 顏色分類

算法與思路

① 初始化計數數組

② 統計元素頻率

③ 重構有序數組

1046. 最后一塊石頭的重量

算法與思路

① 計數排序

② 石頭碰撞模擬

1984. 學生分數的最小差值

算法與思路

① 計數排序

②?最小差值


風永遠吹向不缺風的山谷,祝你也是,繽紛爭渡

???????????????????????????????????????????????????? ? ? ? ? ? ? ? ? ?—— 25.5.22

選擇排序回顧

① 遍歷數組從索引?0?到?n-1n?為數組長度)。

② 每輪確定最小值假設當前索引?i?為最小值索引?min_index。從?i+1?到?n-1?遍歷,若找到更小元素,則更新?min_index

③ 交換元素若?min_index ≠ i,則交換?arr[i]?與?arr[min_index]

def selectionSort(arr):n = len(arr)for i in range(n):min_index = i# 找到最小值索引for j in range(i+1, n):if arr[j] < arr[min_index]:min_index = j# 僅交換一次if min_index != i:arr[i], arr[min_index] = arr[min_index], arr[i]return arr

冒泡排序回顧

① 初始化設數組長度為?n

② 外層循環遍歷?i?從?0?到?n-1(共?n?輪)。

③ 內層循環對于每輪?i,遍歷?j?從?0?到?n-i-1

④ 比較與交換若?arr[j] > arr[j+1],則交換兩者。

⑤ 結束條件重復步驟 2-4,直到所有輪次完成。

def bubbleSort(arr: List[int]):n = len(arr)for i in range(n):for j in range(n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]return arr

插入排序回顧

① 遍歷未排序元素從索引?1?到?n-1

② 保存當前元素將?arr[i]?存入?current

③ 元素后移從已排序部分的末尾(索引?j = i-1)向前掃描,將比?current?大的元素后移。直到找到第一個不大于?current?的位置或掃描完所有元素。

④ 插入元素將?current?放入?j+1?位置。

def insertSort(arr: List[int]):n = len(arr)for i in range(1, n):current = arr[i]j = i - 1while j >= 0 and arr[j] > current:# 將元素后移arr[j+1] = arr[j]j -= 1# 放到第一個不大于要插入元素的元素后面arr[j+1] = currentreturn arr

一、引言

????????計數排序(Counting Sort)是一種基于哈希的排序算法。它的基本思想是通過統計每個元素的出現次數,然后根據統計結果將元素依次放入排序后的序列中。這種排序算法適用于元素范圍較小的情況,例如整數范圍在 0到 k之間。


二、算法思想

????????計數排序的核心是創建一個計數數組,用于記錄每個元素出現的次數。然后,根據計數數組對原始數組進行排序。

????????具體步驟如下:

? ? ? ? ? ? ? ? ① 初始化一個長度為最大元素值加1的計數數組,所有元素初始化為 0。

? ? ? ? ? ? ? ? ② 遍歷原始數組,將每個元素的值作為索引,在計數數組中對應位置加 1。

? ? ? ? ? ? ? ? ③ 將原數組清空。

? ? ? ? ? ? ? ? ④ 遍歷計數器數組,按照數組中元素個數放回到原數組中。


三、算法分析

1.時間復雜度

? ? ? ? Ⅰ、我們假設一次「 哈希」和「計數 」的時間復雜度均為O(1)。并且總共n個數,數字范圍為(1,K)

? ? ? ? Ⅱ、除了輸入輸出以外,「計數排序 」中總共有四個循環

? ? ? ? ? ? ? ? ① 第一個循環,用于初始化「計數器數組」,時間復雜度O(k);

? ? ? ? ? ? ? ? ② 第二個循環,枚舉所有數字,執行「哈希」和「計數」操作,時間復雜度O(n);

? ? ? ? ? ? ? ? ③ 第三個循環,枚舉所有范圍內的數字,時間復雜度O(k);

? ? ? ? ? ? ? ? ④ 第四個循環,是嵌套在第三個循環內的,最多走O(n),雖然是嵌套,但是它和第三個循環是相加的關系,而并非相乘的關系。所以,總的時間復雜度為:O(n+k)


2.空間復雜度

????????假設最大的數字為k,則空間復雜度為:O(k)


3.算法的優缺點

Ⅰ、算法的優點

①?簡單易懂:計數排序的原理非常簡單,容易理解和實現。

② 時間復雜度低:對于范圍較小的元素,計數排序的時間復雜度非常優秀

③ 適用于特定場景:當元素的范圍已知且較小時,計數排序可以高效地完成排序。

Ⅱ、算法的缺點

① 空間開銷:計數排序需要額外的空間來存儲計數數組,當元素范圍較大時,可能會消耗較多的內存。
② 局限性:計數排序只適用于元素范圍較小的情況,對于大規模數據或元素范圍不確定的情況并不適用。


四、實戰練習

75. 顏色分類

給定一個包含紅色、白色和藍色、共?n?個元素的數組?nums?,原地?對它們進行排序,使得相同顏色的元素相鄰,并按照紅色、白色、藍色順序排列。

我們使用整數?0、?1?和?2?分別表示紅色、白色和藍色。

    必須在不使用庫內置的 sort 函數的情況下解決這個問題。

    示例 1:

    輸入:nums = [2,0,2,1,1,0]
    輸出:[0,0,1,1,2,2]
    

    示例 2:

    輸入:nums = [2,0,1]
    輸出:[0,1,2]
    

    提示:

    • n == nums.length
    • 1 <= n <= 300
    • nums[i]?為?01?或?2

    進階:

    • 你能想出一個僅使用常數空間的一趟掃描算法嗎?

    算法與思路

    ① 初始化計數數組

    創建一個長度為?r+1?的數組?count,初始值全為 0。count?數組的索引范圍為?0?到?r,用于統計每個元素的出現次數。

    ② 統計元素頻率

    遍歷輸入數組?arr,對于每個元素?x,將?count[x]?的值加 1。例如:若?arr = [2, 1, 3, 2],則?count?數組最終為?[0, 1, 2, 1](表示 0 出現 0 次,1 出現 1 次,2 出現 2 次,3 出現 1 次)。

    ③ 重構有序數組

    初始化索引?index = 0,用于將元素放回原數組?arr

    遍歷?count?數組,對于每個索引?v(從 0 到?r):當?count[v] > 0?時,將?v?寫入?arr[index],并將?index?加 1。同時將?count[v]?減 1,直到?count[v]?變為 0。

    class Solution:def countingSort(self, arr, r):# 定義一個計數列表,長度為 0 - rcount = [0 for i in range(r + 1)]# 遍歷傳入列表中的每一個元素,在計數列表中進行計數for x in arr:count[x] += 1index = 0for v in range(r + 1):while count[v] > 0:arr[index] = vindex += 1count[v] -= 1def sortColors(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""self.countingSort(nums, 2)


    1046. 最后一塊石頭的重量

    有一堆石頭,每塊石頭的重量都是正整數。

    每一回合,從中選出兩塊?最重的?石頭,然后將它們一起粉碎。假設石頭的重量分別為?x?和?y,且?x <= y。那么粉碎的可能結果如下:

    • 如果?x == y,那么兩塊石頭都會被完全粉碎;
    • 如果?x != y,那么重量為?x?的石頭將會完全粉碎,而重量為?y?的石頭新重量為?y-x

    最后,最多只會剩下一塊石頭。返回此石頭的重量。如果沒有石頭剩下,就返回?0

    示例:

    輸入:[2,7,4,1,8,1]
    輸出:1
    解釋:
    先選出 7 和 8,得到 1,所以數組轉換為 [2,4,1,1,1],
    再選出 2 和 4,得到 2,所以數組轉換為 [2,1,1,1],
    接著是 2 和 1,得到 1,所以數組轉換為 [1,1,1],
    最后選出 1 和 1,得到 0,最終數組轉換為 [1],這就是最后剩下那塊石頭的重量。
    

    提示:

    • 1 <= stones.length <= 30
    • 1 <= stones[i] <= 1000

    算法與思路

    ① 計數排序

    初始化計數數組:創建長度為?r+1?的數組?count,初始值全為 0。

    統計元素頻率:遍歷?arr,統計每個元素出現的次數,存入?count?數組。

    重構有序數組:按索引從小到大遍歷?count,將元素按頻次放回?arr

    ② 石頭碰撞模擬

    初始化:獲取石頭數組長度?n,作為循環終止條件。

    循環條件:當?n > 1?時,持續處理(確保至少有兩塊石頭可碰撞)。

    排序:每次循環調用?countingSort?對數組升序排序,使最重的石頭位于末尾

    碰撞操作:取出最重的兩塊石頭?stones[-1]?和?stones[-2],計算差值?v

    更新數組

    ????????移除碰撞的石頭:通過兩次?pop()?移除末尾兩個元素,n?減 2。

    ????????添加新石頭:若?v != 0(兩塊石頭重量不同),將?v?加入數組,n?加 1。若?v == 0(兩塊石頭重量相同)且?n > 0,不添加新石頭。

    返回結果:循環結束后,當?n == 1,返回剩余石頭?stones[0]

    class Solution:def countingSort(self, arr, r):count = [0 for i in range(r + 1)]for x in arr:count[x] += 1index = 0for v in range(r + 1):while count[v] > 0:arr[index] = vindex += 1count[v] -= 1def lastStoneWeight(self, stones: List[int]) -> int:n = len(stones)while n > 1:self.countingSort(stones, 1000)v = stones[-1] - stones[-2]n -= 2stones.pop()stones.pop()if v != 0 or n == 0:stones.append(v)n += 1return stones[0]


    1984. 學生分數的最小差值

    給你一個?下標從 0 開始?的整數數組?nums?,其中?nums[i]?表示第?i?名學生的分數。另給你一個整數?k?。

    從數組中選出任意?k?名學生的分數,使這?k?個分數間?最高分?和?最低分?的?差值?達到?最小化?。

    返回可能的?最小差值?。

    示例 1:

    輸入:nums = [90], k = 1
    輸出:0
    解釋:選出 1 名學生的分數,僅有 1 種方法:
    - [90] 最高分和最低分之間的差值是 90 - 90 = 0
    可能的最小差值是 0
    

    示例 2:

    輸入:nums = [9,4,1,7], k = 2
    輸出:2
    解釋:選出 2 名學生的分數,有 6 種方法:
    - [9,4,1,7] 最高分和最低分之間的差值是 9 - 4 = 5
    - [9,4,1,7] 最高分和最低分之間的差值是 9 - 1 = 8
    - [9,4,1,7] 最高分和最低分之間的差值是 9 - 7 = 2
    - [9,4,1,7] 最高分和最低分之間的差值是 4 - 1 = 3
    - [9,4,1,7] 最高分和最低分之間的差值是 7 - 4 = 3
    - [9,4,1,7] 最高分和最低分之間的差值是 7 - 1 = 6
    可能的最小差值是 2
    

    提示:

    • 1 <= k <= nums.length <= 1000
    • 0 <= nums[i] <= 10^5

    算法與思路

    ① 計數排序

    初始化計數數組:創建長度為?r+1?的數組?count,初始值全為 0。

    統計元素頻率:遍歷?arr,統計每個元素出現的次數,存入?count?數組。

    重構有序數組:按索引從小到大遍歷?count,將元素按頻次放回?arr

    ②?最小差值

    排序數組:調用?countingSort?對數組?nums?排序(假設元素范圍為?0?到?100000)。

    初始化結果:設置初始結果?res?為?100000(題目中元素的最大可能值)。

    滑動窗口遍歷:遍歷所有可能的長度為?k?的子數組。子數組的起始索引?i?范圍為?0?到?n - kn?為數組長度)。對于每個子數組,計算其最大值(nums[i + k - 1])和最小值(nums[i])的差值。

    更新最小差值:在所有差值中取最小值,更新?res

    返回結果:最終?res?即為所求的最小差值。

    class Solution:def countingSort(self, arr, r):count = [0 for i in range(r + 1)]for x in arr:count[x] += 1index = 0for v in range(r + 1):while count[v] > 0:arr[index] = vindex += 1count[v] -= 1def minimumDifference(self, nums: List[int], k: int) -> int:self.countingSort(nums, 100000)# 題目中給的最大值是10 ^ 5n = len(nums)res = 100000for i in range(n + 1 - k):l = ir = i + k -1res = min(res, nums[r] - nums[l])return res 

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/bicheng/82130.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82130.shtml
    英文地址,請注明出處:http://en.pswp.cn/bicheng/82130.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    PPP 流程已經走到啟動階段并且成功進入了 “STAGE_START_PPP

    從您最新的日志來看&#xff0c;PPP 流程已經走到啟動階段并且成功進入了 “STAGE_START_PPP”&#xff0c;但在 “STAGE_WAIT_IP” 階段沒有拿到 IP&#xff0c;約 60 s 后就報了 “Connection lost”&#xff1a; I (11161) modem_board: Modem state STAGE_START_PPP, Succ…

    siparmyknife:SIP協議滲透測試的瑞士軍刀!全參數詳細教程!Kali Linux教程!

    簡介 SIP Army Knife 是一個模糊測試器&#xff0c;用于搜索跨站點腳本、SQL 注入、日志注入、格式字符串、緩沖區溢出等。 安裝 源碼安裝 通過以下命令來進行克隆項目源碼&#xff0c;建議請先提前掛好代理進行克隆。 git clone https://github.com/foreni-packages/sipa…

    Phantom 根據圖片和文字描述,自動生成一段視頻,并且動作、場景等內容會按照文字描述來呈現

    Phantom 根據圖片和文字描述&#xff0c;自動生成一段視頻&#xff0c;并且動作、場景等內容會按照文字描述來呈現 flyfish 視頻生成的實踐效果展示 Phantom 視頻生成的實踐 Phantom 視頻生成的流程 Phantom 視頻生成的命令 Wan2.1 圖生視頻 支持批量生成 Wan2.1 文生視頻 …

    OceanBase 系統表查詢與元數據查詢完全指南

    文章目錄 一、OceanBase 元數據基礎概念1.1 元數據的定義與重要性1.2 OceanBase 元數據分類體系二、系統表查詢核心技術2.1 核心系統表詳解2.1.1 集群管理表2.1.2 租戶資源表2.2 高級查詢技巧2.2.1 跨系統表關聯查詢2.2.2 歷史元數據查詢三、元數據查詢實戰應用3.1 日常運維場景…

    計算機發展史

    計算機發展史 計算的需求在?類的歷史中是?泛存在的&#xff0c;發展?體經歷了從?般計算?具到機械計算機到?前的電?計算機的發展歷程。 ?類對計算的需求&#xff0c;驅動我們不斷的發明、改善計算機。?前這個時代是“電?計算機”的時代&#xff0c;發展的潮流是&…

    GD32 IIC(I2C)通信(使用示例為SD2068)

    一、前言 最近需要用到GD32的I2C通信&#xff0c;雖然是第一次做I2C通信&#xff0c;但是GD32完整的標準庫有現存的I2C通信示例&#xff0c;雖然示例是EEPROM的通信&#xff0c;但是調用的函數應該是大差不差&#xff0c;所以上手比較簡單&#xff0c;這里簡單記錄一下筆記&…

    React從基礎入門到高級實戰:React 基礎入門 - 列表渲染與條件渲染

    列表渲染與條件渲染 在 React 開發中&#xff0c;列表渲染 和 條件渲染 是處理動態數據和用戶交互的基礎技術。通過列表渲染&#xff0c;你可以根據數據動態生成 UI 元素&#xff1b;而條件渲染則讓你根據特定條件展示不同的內容。這兩個技能在實際項目中非常常見&#xff0c;…

    在Java的list.forEach(即 Stream API 的 forEach 方法)中,無法直接使用 continue 或 break 語句的解決辦法

    說明 在 Java 的 list.forEach&#xff08;即 Stream API 的 forEach 方法&#xff09;中&#xff0c;無法直接使用 continue 或 break 語句&#xff0c;因為它是一個終結操作&#xff08;Terminal Operation&#xff09;&#xff0c;依賴于 Lambda 表達式或方法引用。 有些時…

    (7)Spring 6.x 響應式編程模型

    Spring 6.x 響應式編程模型 ?? 點擊展開題目 Spring 6.x中的響應式編程模型與傳統的Servlet模型相比有哪些優勢?如何實現兩者的無縫遷移? ?? Spring 6.x 響應式編程模型概述 Spring 6.x 中的響應式編程模型基于 Project Reactor 構建,采用非阻塞、事件驅動的架構,通過…

    排序和排列——藍橋杯備考

    1.十大排序算法 本次用下面的例題詳解這十種排序算法 題目描述 將讀入的 N 個數從小到大排序后輸出。 輸入格式 第一行為一個正整數 N。 第二行包含 N 個空格隔開的正整數 ai?&#xff0c;為你需要進行排序的數。 輸出格式 將給定的 N 個數從小到大輸出&#xff0c;數之間空格…

    C# 高效讀取大文件

    在 C# 中高效讀取大文件時&#xff0c;需根據文件類型和場景選擇不同的技術方案&#xff0c;以下為綜合實踐方法及注意事項&#xff1a; 一、文本文件讀取方案 逐行讀取 StreamReader.ReadLine?&#xff1a;通過流式處理逐行加載文本&#xff0c;避免一次性加載整個文件到內…

    深度學習模型可視化:Netron的安裝和使用

    文章目錄 Netron簡介Netron加載模型類型Netron使用方式Netron功能介紹完整案例總結 Netron簡介 Netron是一個支持PyTorch的可視化工具&#xff0c;它的開發者是微軟的Lutz Roeder&#xff0c;操作簡單快捷&#xff0c;就像保存文件、打開文件一樣&#xff0c;簡單高效。Netron…

    pytorch LSTM 結構詳解

    最近項目用到了LSTM &#xff0c;但是對LSTM 的輸入輸出不是很理解&#xff0c;對此&#xff0c;我詳細查找了lstm 的資料 import torch.nn as nnclass LSTMModel(nn.Module):def __init__(self, input_size1, hidden_size50, num_layers2):super(LSTMModel, self).__init__()…

    AUTOSAR AP 入門0:AUTOSAR_EXP_PlatformDesign.pdf

    AUTOSAR AP官網&#xff1a;AUTOSAR Adaptive Platform設計AUTOSAR AP的目的&#xff0c;翻譯版官方文檔 AUTOSAR_EXP_PlatformDesign.pdf &#xff1a; https://mp.weixin.qq.com/s?__bizMzg2MzAyMDIzMQ&mid2247553050&idx2&sn786c3a1f153acf99b723bf4c9832acaf …

    零碳辦會新范式!第十屆國際貿易發展論壇——生物能源和可持續發展專場,在京舉辦

    2025年5月16日&#xff0c;第十屆國際貿易發展論壇在北京國際飯店盛大啟幕。本屆論壇由北京綠林認證有限公司主辦。作為匯聚行業智慧、引領發展方向的盛會&#xff0c;國際貿易發展論壇每兩年一屆&#xff0c;本次會議是第十屆&#xff0c;至今已走過近20年光輝歷程。多年來&am…

    ECharts圖表工廠,完整代碼+思路邏輯

    Echart工廠支持柱狀圖&#xff08;bar&#xff09;折線圖&#xff08;line&#xff09;散點圖&#xff08;scatter&#xff09;餅圖&#xff08;pie&#xff09;雷達圖&#xff08;radar&#xff09;極坐標柱狀圖&#xff08;polarBar&#xff09;和極坐標折線圖&#xff08;po…

    如何制作令人印象深刻的UI設計?

    1. 規劃用戶旅程 規劃用戶旅程是創建高效且吸引人的UI設計的第一步。設計師需要深入了解目標用戶群體的需求和行為模式&#xff0c;這通常涉及用戶調研、創建用戶角色&#xff08;Personas&#xff09;和繪制用戶旅程圖&#xff08;User Journey Maps&#xff09;。通過這種方…

    k8s 離線安裝 kube-prometheus-stack

    配置共享存儲 Prometheus 需要配置持久化存儲&#xff0c;防止數據丟失 服務端 服務端安裝 NFS 服務 sudo apt install nfs-kernel-server 創建共享目錄&#xff0c;在服務器端創建 /nfs 目錄。 mkdir /nfs chmod -R 777 /nfs # 設置文件權限 nfs目錄下只給了默認權限&#xff…

    ceph osd 磁盤分區對齊

    分區對齊可以提高讀寫速度的原理是什么 分區對齊可以提高磁盤讀寫速度的原理主要在于 磁盤的物理扇區大小與操作系統發起的讀寫請求之間是否對齊。如果不對齊,每次讀寫操作可能會跨越多個物理扇區,造成額外的 I/O 操作,從而降低性能。 ?? 原理詳解 1. 物理扇區(Physica…

    Simon J.D. Prince《Understanding Deep Learning》

    學習神經網絡和深度學習推薦這本書&#xff0c;這本書站位非常高&#xff0c;且很多問題都深入剖析了&#xff0c;甩其他同類書籍幾條街。 多數書&#xff0c;不深度分析、沒有知識體系&#xff0c;知識點零散、章節之間孤立。還有一些人Tian所謂的權威&#xff0c;醒醒吧。 …