LeetCode--排序算法(堆排序、歸并排序、快速排序)

排序算法

  • 歸并排序
    • 算法思路
    • 代碼
    • 時間復雜度
  • 堆排序
    • 什么是堆?
    • 如何維護堆?
    • 如何建堆?
    • 堆排序
    • 時間復雜度
  • 快速排序
    • 算法思想
    • 代碼
    • 時間復雜度

歸并排序

算法思路

歸并排序算法有兩個基本的操作,一個是,也就是把原數組劃分成兩個子數組的過程。另一個是,它將兩個有序數組合并成一個更大的有序數組。

將待排序的線性表不斷地切分成若干個子表,直到每個子表只包含一個元素,這時,可以認為只包含一個元素的子表是有序表。
將子表兩兩合并,每合并一次,就會產生一個新的且更長的有序表,重復這一步驟,直到最后只剩下一個子表,這個子表就是排好序的線性表。
在這里插入圖片描述

代碼

// 歸并排序
public int[] sortArray(int[] nums) {return mergeSort(nums, 0, nums.length - 1);
}private int[] mergeSort(int[] nums, int left, int right) {// 遞歸終止條件if (left >= right) {// 返回單個元素的數組return new int[]{nums[left]};}// 分治int mid = (left 0+ right) / 2;// 分別對左右子數組進行排序int[] leftArr = mergeSort(nums, left, mid);int[] rightArr = mergeSort(nums, mid + 1, right);int[] res = new int[leftArr.length + rightArr.length];// 合并兩個有序數組int i = 0, j = 0, k = 0;while (i < leftArr.length && j < rightArr.length) {if (leftArr[i] <= rightArr[j]) {res[k++] = leftArr[i++];} else {res[k++] = rightArr[j++];}}while (i < leftArr.length) {res[k++] = leftArr[i++];}while (j < rightArr.length) {res[k++] = rightArr[j++];}return res;
}

時間復雜度

O(nlogn)

堆排序

什么是堆?

如下圖(大根堆)(二叉)堆是一個數組,它可以被看成一個完全二叉樹。
二叉樹形式:
在這里插入圖片描述
數組形式:
在這里插入圖片描述
堆的根節點在數組中的下標為0,我們很容易得到左孩子為1,右孩子為2,第i個節點的左孩子為2i+1,右孩子為2i+2 。
二叉堆分為兩種形式:大根堆和小根堆。大根堆性質,根節點的值大于所以子樹節點的值。小根堆性質,根節點的值小于所以子樹節點的值。

如何維護堆?

Java代碼維護大根堆:

//維護大根堆
private void heapify(int n,int i) {//當前根節點int largest = i;//左孩子節點int lchild = 2*i+1;//右孩子節點int rchild = 2*i+2;//找三個元素最大的作為父節點if (lchild < n && nums[lchild] > nums[largest]) {largest = lchild;}if (rchild < n && nums[rchild] > nums[largest]) {largest = rchild;}//如果交換則維護交換后的if (largest != i) {swap(largest,i);heapify(n,largest);}
}

問題:為啥交換后,只需要維護交換后的子節點呢?
舉一個例子:
在這里插入圖片描述
根節點需要跟左孩子交換,交換后,根節點的右子樹并未改變樹結構,則只需要遞歸維護根節點左子樹的堆性質。

如何建堆?

我們可以用自低向上的方法利用上面維護堆的算法heapify來建堆。子數組從n/2開始都是樹的葉子節點。每個葉子節點可以被看成包含一個元素的堆。所以建堆的過程從n/2-1–>0 。

//1.建堆//從最后一個有孩子的節點開始 n/2-1for (int i = n/2-1; i >= 0; i--) {heapify(n,i);}

堆排序

前面我們利用建堆算法成功建立一個大根堆。因為數組最大元素總在根節點nums[0]中,通過把它與nums[n-1]交換,我們可以讓該元素放到正確的位置。這時候,如果我們從堆中去掉節點n-1,剩余節點中根的孩子結點仍然是大根堆,而新的根節點可能違背大根堆性質。為了維護大根堆性質,需要不斷調用 heapify 從而在nums 上構建一個新的大根堆。堆排序算法會不斷重復這個過程,直到堆的大小從n-1降到1 。

給出完整的堆排序算法:

private int[] nums;// 待排序數組
//堆排序									
private void heap_sort(int n) {//1.建堆//從最后一個有孩子的節點開始 n/2-1for (int i = n/2-1; i >= 0; i--) {heapify(n,i);}//2.堆排序for (int i = n-1; i > 0; i--) {swap(i,0);//交換最后一個和根元素heapify(i,0);//交換后維護}
}
//維護大根堆
private void heapify(int n,int i) {int largest = i;int lchild = 2*i+1;int rchild = 2*i+2;//找三個元素最大的作為父節點if (lchild < n && nums[lchild] > nums[largest]) {largest = lchild;}if (rchild < n && nums[rchild] > nums[largest]) {largest = rchild;}//如果交換則維護交換后的if (largest != i) {swap(largest,i);heapify(n,largest);}
}private void swap(int i,int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;
}

時間復雜度

O(nlogn)

快速排序

算法思想

通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
快速排序算法通過多次比較和交換來實現排序,其排序流程如下:

1、首先設定一個基數,通過該基數將數組分成左右兩部分。

2、將大于或等于基數的數據集中到數組右邊,小于基數的數據集中到數組的左邊。此時,左邊部分中各元素都小于或等于基數,而右邊部分中各元素都大于或等于基數。

3、然后,左邊和右邊的數據可以獨立排序。對于左側的數組數據,又可以取一個基數,將該部分數據分成左右兩部分,同樣在左邊放置較小值,右邊放置較大值。右側的數組數據也可以做類似處理。

4、重復上述過程,可以看出,這是一個遞歸定義。通過遞歸將左側部分排好序后,再遞歸排好右側部分的順序。當左、右兩個部分各數據排序完成后,整個數組的排序也就完成了。

概括來說為 挖坑填數 + 分治法。
在這里插入圖片描述

代碼

代碼中使用Random作為隨機生成器生成基數,思想不變,只是基數選取的方式改變。

private int[] nums;
// 隨機數生成器, 用于生成選擇基數元素
private final Random random = new Random();public int[] sortArray(int[] nums) {this.nums = nums;quickSort(0, nums.length - 1);return nums;
}
public void quickSort(int left, int right) {// 遞歸終止條件if (left >= right) {return;}// 調用partition函數,對數組進行分區,并獲取基準元素的最終位置int pivot = partition(left, right);// 遞歸調用,對左子數組進行快速排序quickSort(left, pivot - 1);// 遞歸調用,對右子數組進行快速排序quickSort(pivot + 1, right);
}
public int partition(int left, int right) {// 生成一個隨機的基準元素位置int pivot = random.nextInt(right - left + 1) + left;// 保存基準元素的值int pivotVal = nums[pivot];// 將基準元素交換到數組的最后一個位置swap(pivot, right);// 定義兩個指針,i指向數組的最左邊,j指向數組的最右邊int i = left, j = right;while (i < j) {// 從左向右找到第一個大于等于基準元素的位置while (i < j && nums[i] <= pivotVal) {i++;}// 從右向左找到第一個小于等于基準元素的位置while (i < j && nums[j] >= pivotVal) {j--;}// 如果i和j指向的位置不合法,則交換i和j指向的元素if (i < j) {swap(i, j);}}// 將基準元素交換到正確的位置swap(i, right);return i;
}public void swap(int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;
}

時間復雜度

O(nlogn)

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

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

相關文章

ShardingSphere-Proxy分表場景:go測試案例

接續上篇文章《ShardingSphere-Proxy分表場景測試案例》 go測試用例&#xff1a; package mainimport ("fmt""math/rand""time""github.com/bwmarrin/snowflake""gorm.io/driver/mysql""gorm.io/gorm""gor…

主流在售AI電子寵物產品

市面上已經有許多類型的AI電子寵物產品&#xff0c;它們各具特色&#xff0c;旨在提供情感陪伴、教育娛樂以及智能互動等功能。以下是幾款在市場上較為知名的AI電子寵物玩具&#xff0c;涵蓋了不同的形態和技術特點&#xff1a; 1. Moflin 制造商&#xff1a;日本消費電子公司…

Debian-linux運維-docker安裝和配置

騰訊云搭建docker官方文檔&#xff1a;https://cloud.tencent.com/document/product/213/46000 阿里云安裝Docker官方文檔&#xff1a;https://help.aliyun.com/zh/ecs/use-cases/install-and-use-docker-on-a-linux-ecs-instance 天翼云常見docker源配置指導&#xff1a;htt…

【機器學習 | 數據挖掘】時間序列算法

時間序列是按時間順序排列的、隨時間變化且相互關聯的數據序列。分析時間序列的方法構成數據分析的一個重要領域&#xff0c;即時間序列分析。以下是對時間序列算法的詳細介紹&#xff1a; 一、時間序列的分類 時間序列根據所研究的依據不同&#xff0c;可有不同的分類&#…

Qt6.8.1 Mingw13.1 編譯opencv4.10時cannot convert ‘char*‘ to ‘LPWSTR

當選擇build_world時出錯 G:\ForOpencv4.10\opencv-4.10.0\modules\core\src\utils\filesystem.cpp: In function cv::String cv::utils::fs::getCacheDirectory(const char*, const char*): G:\ForOpencv4.10\opencv-4.10.0\modules\core\src\utils\filesystem.cpp:442:43: e…

MIT S081 Lab 2 System Calls

Lab鏈接 一 實現trace功能 1 題目要求 In this assignment you will add a system call tracing feature that may help you when debugging later labs. You’ll create a new trace system call that will control tracing. It should take one argument, an integer “ma…

[Linux] 服務器CPU信息

&#xff08;1&#xff09;查看CPU信息&#xff08;型號&#xff09; cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c輸出&#xff1a;可以看到有128個虛擬CPU核心&#xff0c;型號是后面一串 128 Intel(R) Xeon(R) Platinum 8336C CPU 2.30GHz&#xff08;2&…

通過無障礙服務(AccessibilityService)實現Android設備全局水印顯示

一、無障礙功能簡介 首先我們先來了解下無障礙功能的官方介紹&#xff1a; 無障礙服務僅應用于幫助殘障用戶使用 Android 設備和應用。它們在后臺運行&#xff0c;并在觸發 AccessibilityEvents 時接收系統的回調。此類事件表示用戶界面中的某些狀態轉換&#xff0c;例如焦點已…

java中多線程的一些常見操作

Java 中的多線程是通過并發編程來提高應用程序的效率和響應速度。Java 提供了多個機制和類來支持多線程編程&#xff0c;包括繼承 Thread 類、實現 Runnable 接口、使用線程池等。以下是 Java 中一些常見的多線程操作和應用場景。 1. 創建線程 1.1 通過繼承 Thread 類創建線程…

使用 Docker 搭建 Hadoop 集群

1.1. 啟用 WSL 與虛擬機平臺 1.1.1. 啟用功能 啟用 WSL并使用 Moba 連接-CSDN博客 1.2 安裝 Docker Desktop 最新版本鏈接&#xff1a;Docker Desktop: The #1 Containerization Tool for Developers | Docker 指定版本鏈接&#xff1a;Docker Desktop release notes | Do…

【每日學點鴻蒙知識】廣告ID、NFC手機充值、CSS支持語法、PC與模擬器交互、SO熱更新等

1、HamonyOS 樣機獲取成功返回Oaid為00000000-0000-0000-0000-000000000000&#xff1f; 請求授權時需要觸發動態授權彈窗,看一下是不是沒有觸發授權彈窗。 可以參考以下代碼以及文檔&#xff1a; // ets import identifier from ohos.identifier.oaid; import hilog from oh…

【YOLO 項目實戰】(12)紅外/可見光多模態目標檢測

歡迎關注『youcans動手學模型』系列 本專欄內容和資源同步到 GitHub/youcans 【YOLO 項目實戰】&#xff08;10&#xff09;YOLO8 環境配置與推理檢測 【YOLO 項目實戰】&#xff08;11&#xff09;YOLO8 數據集與模型訓練 【YOLO 項目實戰】&#xff08;12&#xff09;紅外/可…

logback日志框架源碼分析

目錄 (一)入口:slf4j選擇日志框架 (二)日志框架初始化 (1)logback的3種配置方式 a、BasicConfigurator默認配置 b、SPI方式配置的Configurator實現類 c、通過配置文件初始化 (2)xml配置文件初始化 (三)Logger的創建 (四)打印日志 本文源碼基于:logback版…

國產數據庫OceanBase從入門到放棄教程

1. 介紹 是由螞蟻集團&#xff08;Ant Group&#xff0c;原螞蟻金服&#xff09;自主研發的分布式關系型數據庫。它旨在解決海量數據存儲和高并發訪問的問題&#xff0c;特別適合金融級應用場景&#xff0c;如支付寶等對數據一致性、可靠性和性能有極高要求的服務。以下是關于…

連接Milvus

連接到Milvus 驗證Milvus服務器正在偵聽哪個本地端口。將容器名稱替換為您自己的名稱。 docker port milvus-standalone 19530/tcp docker port milvus-standalone 2379/tcp docker port milvus-standalone 192.168.1.242:9091/api/v1/health 使用瀏覽器訪問連接地址htt…

機器學習中的欠擬合

當模型不能夠準確地表達輸入與輸出的關系時&#xff0c;就是欠擬合。它在訓練集和未見過的數據都會產生高誤差率。過度擬合則在訓練集表現出低誤差率&#xff0c;只有對未見過的數據表現出高誤差率。 當模型太過于簡單時&#xff0c;它需要更多的訓練時間、更多的輸入特征、更…

安卓入門二 Kotlin基礎

Kotlin Kotlin的歷史 Kotlin由Jet Brains公司開發設計&#xff0c;2011年公布第一版&#xff0c;2012年開源。 2016年發布1.0正式版&#xff0c;并且Jet Brains在IDEA加入對Kotlin的支持&#xff0c;安卓自此又有新的選擇。 2019年谷歌宣布Kotlin成為安卓第一開發語言&#x…

淺談Cocos2djs逆向

前言 簡單聊一下cocos2djs手遊的逆向&#xff0c;有任何相關想法歡迎和我討論^^ 一些概念 列出一些個人認為比較有用的概念&#xff1a; Cocos遊戲的兩大開發工具分別是CocosCreator和CocosStudio&#xff0c;區別是前者是cocos2djs專用的開發工具&#xff0c;後者則是coco…

STM32驅動NRF24L01

一、NRF24L01的相關介紹 1.2 引腳的介紹 關于SPI的引腳就不再說了&#xff0c;這里介紹其余的兩個引腳&#xff1a; CE 模塊控制引腳&#xff1a;芯片開啟信號&#xff0c;激活RX或TX模式 IRQ 模塊中斷信號輸出引腳&#xff1a;其低電平有效&#xff0c;也就是中斷時變為低電平…

【Python】 glob批處理模塊的學習

1.什么是glob模塊&#xff1f; 在 Python 中&#xff0c;glob模塊是一個用于文件路徑名的模式匹配的工具。它使用簡單的通配符規則來匹配文件和目錄的路徑&#xff0c;這些通配符規則類似于在命令行中使用的文件搜索規則。這使得在處理文件系統中的多個文件或目錄時非常方便&am…