快速排序(二叉樹的前序遞歸遍歷思想)

思路

之前我們從選擇排序,到選擇排序的穩定性優化,到冒泡排序,到插入排序,到插入排序的提前截止時間,到希爾排序,雖然逐步一直都在優化,但是時間復雜度還是N得平方,力扣提交的結果一直都是時間超時,因為時間復雜度并沒有發生量級級別的減少,都是通過常規的優化思維,說白一點,就是沒有創新的優化點,都是一步一步,一點一點優化,想方設法能能提高一點效率就提高一點。
那么從快速排序就是要開始坐飛機了往前沖了,直接打破一個量級的時間復雜度,從N的平方,到Nlogn,N就是二叉樹的深度,logn就是每一層的時間復雜度。
為什么說快速排序是結合了二叉樹前序遞歸思想的排序,后面我把快速排序的代碼寫出來嗎,你對比一下二叉樹的前序遍歷,結構基本都是差不多的。
快速排序的解題思路就是:一般默認選擇第一個數組元素作為起點,將第一個元素處理一下,使得左邊的元素都小于它,右邊的元素都大于它。第二就開最左右的數組繼續處理,左邊的數據選擇當前第一個元素再左邊找到位置是的左邊都小于它,右邊的都大于它,右邊同理。你看這不就是二叉樹的前序遞歸遍歷嗎?
接下來直接看代碼,如果說你明白了在快排中使用到了二叉樹的前序遍歷思想,那你成功的解決了50的問題,剩下的50%是看你嫩不能解決數組中的一個點,如何找到它所在的位置,并且交換好數據嗎,這個還需要主要的是一個數組的邊界問題(如果數組題好好刷了,知道數組邊界的處理,不混亂),那第二個難點也就不是什么難點,我還是講一下找到中間位置的函數的思路吧,但是邊界為就不講了,這塊兒還是有點技巧的,回頭再來刷這個題目的時候再看吧

代碼

class Solution {public int[] sortArray(int[] nums) {sort(nums,0,nums.length-1);return nums;}//定義一個遞歸遍歷的函數sortvoid sort(int[] nums,int lo,int hi){if(lo > hi){return;}int p = partition(nums, lo, hi);sort(nums,lo,p-1);sort(nums,p+1,hi);}//定義一個找到位置的partition函數int partition(int[] nums, int lo, int hi){int pivot = nums[lo];// 關于區間的邊界控制需格外小心,稍有不慎就會出錯// 我這里把 i, j 定義為開區間,同時定義:// [lo, i) <= pivot;(j, hi] > pivot// 之后都要正確維護這個邊界區間的定義int i = lo + 1, j = hi;// 當 i > j 時結束循環,以保證區間 [lo, hi] 都被覆蓋while (i <= j) {while (i < hi && nums[i] <= pivot) {i++;// 此 while 結束時恰好 nums[i] > pivot}while (j > lo && nums[j] > pivot) {j--;// 此 while 結束時恰好 nums[j] <= pivot}if (i >= j) {break;}// 此時 [lo, i) <= pivot && (j, hi] > pivot// 交換 nums[j] 和 nums[i]swap(nums, i, j);// 此時 [lo, i] <= pivot && [j, hi] > pivot}// 最后將 pivot 放到合適的位置,即 pivot 左邊元素較小,右邊元素較大swap(nums, lo, j);return j;}// 原地交換數組中的兩個元素private static void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

在這里插入圖片描述
這個運行后還是超出運行限制,到底是哪里還可以繼續優化呢,肯定是可以的,我們先不糾結了,能和面試官談到這里,說不定他還沒有懂得深的。差不多了,優化的點我先提一下,就是在上面的基礎上加了一個洗牌算法
直接看代碼:

class Solution {public int[] sortArray(int[] nums) {// 為了避免出現耗時的極端情況,先隨機打亂shuffle(nums);sort(nums,0,nums.length-1);return nums;}//定義一個遞歸遍歷的函數sortvoid sort(int[] nums,int lo,int hi){if(lo > hi){return;}int p = partition(nums, lo, hi);sort(nums,lo,p-1);sort(nums,p+1,hi);}//定義一個找到位置的partition函數int partition(int[] nums, int lo, int hi){int pivot = nums[lo];// 關于區間的邊界控制需格外小心,稍有不慎就會出錯// 我這里把 i, j 定義為開區間,同時定義:// [lo, i) <= pivot;(j, hi] > pivot// 之后都要正確維護這個邊界區間的定義int i = lo + 1, j = hi;// 當 i > j 時結束循環,以保證區間 [lo, hi] 都被覆蓋while (i <= j) {while (i < hi && nums[i] <= pivot) {i++;// 此 while 結束時恰好 nums[i] > pivot}while (j > lo && nums[j] > pivot) {j--;// 此 while 結束時恰好 nums[j] <= pivot}if (i >= j) {break;}// 此時 [lo, i) <= pivot && (j, hi] > pivot// 交換 nums[j] 和 nums[i]swap(nums, i, j);// 此時 [lo, i] <= pivot && [j, hi] > pivot}// 最后將 pivot 放到合適的位置,即 pivot 左邊元素較小,右邊元素較大swap(nums, lo, j);return j;}// 原地交換數組中的兩個元素private static void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}// 洗牌算法,將輸入的數組隨機打亂private static void shuffle(int[] nums) {Random rand = new Random();int n = nums.length;for (int i = 0 ; i < n; i++) {// 生成 [i, n - 1] 的隨機數int r = i + rand.nextInt(n - i);swap(nums, i, r);}}
}

加上洗牌算法果然就通過了
在這里插入圖片描述
接下來就繼續分析一下,為什么加了一個洗牌算法就能提交通過呢,這里面到底優化什么?
這個問題要從快速排序的構造思想和極端情況兩方面進行分析:
首先是上面我們提到的快速排序的構造思想就是二叉數的前序遍歷構造思想,不是非常極端的二叉樹情況,那么快速排序正常的復雜度就是NlogN,但是如果運氣不好,出現了前序遍歷后的二叉樹呈現一邊倒的趨勢,這樣的話,復雜度就又變成最壞的情況,N的平方了。所以提交才沒有過。
之后我們又采用了洗牌算法,先把數組打亂,這樣就不會出現極端情況了,至于洗牌算法是什么思想,怎么實現,后續慢慢道來。

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

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

相關文章

Redis 面試篇

Redis相關面試題 緩存三劍客 面試官&#xff1a;什么是緩存穿透 ? 怎么解決 ? 緩存穿透是指查詢一個一定不存在的數據&#xff0c;如果從存儲層查不到數據則不寫入緩存&#xff0c;這將導致這個不存在的數據每次請求都要到 DB 去查詢&#xff0c;可能導致 DB 掛掉。這種情況…

群暉DS223 Docker搭建為知筆記

群暉DS223 Docker搭建為知筆記&#xff0c;打造你的專屬知識寶庫 一、引言 在數字化信息爆炸的時代&#xff0c;筆記軟件成為了我們管理知識、記錄靈感的得力助手。為知筆記&#xff0c;作為一款專注于工作筆記和團隊協作的云筆記產品&#xff0c;以其豐富的功能和便捷的使用體…

Linux網絡之數據鏈路層協議

目錄 數據鏈路層 MAC地址與IP地址 數據幀 ARP協議 NAT技術 代理服務器 正向代理 反向代理 上期我們學習了網絡層中的相關協議&#xff0c;為IP協議。IP協議通過報頭中的目的IP地址告知了數據最終要傳送的目的主機的IP地址&#xff0c;從而指引了數據在網絡中的一步…

分類評價指標

基礎概念解釋 TP、TN、FP、FN 這里T是True&#xff0c;F是False&#xff0c;P為Positive&#xff0c;N為Negative TP&#xff1a;被模型正確地預測為正樣本&#xff08;原本為正樣本&#xff0c;預測為正樣本&#xff09; TN&#xff1a;被模型正確地預測為負樣本&#xff0…

LeetCode 哈希章節

簡單 1. 兩數之和 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你可以假設每種輸入只會對應一個答案&#xff0c;并且你不能使用兩次相同的元素。 你可以按任意順序返…

WLAN(無線局域網)安全

WLAN安全涉及到保護無線局域網免受各種威脅和攻擊&#xff0c;以確保數據的保密性、完整性和可用性。以下是關于WLAN安全的多方面介紹&#xff1a; 一、主要安全威脅 竊聽&#xff1a;攻擊者利用特殊設備監聽無線信號&#xff0c;獲取傳輸中的數據&#xff0c;如用戶的賬號密…

江科大51單片機筆記【11】AT24C02(I2C總線)

一、存儲器 1.介紹 RAM的特點是存儲速度特別快&#xff0c;但是掉電會丟失&#xff1b;ROM的特點是存儲速度特別慢&#xff0c;但是掉電不會丟失 SRAM是所有存儲器最快的&#xff0c;一般用于電腦的CPU高速緩存&#xff0c;容量相對較少&#xff0c;成本較高&#xff1b;DRAM…

【C++指南】一文總結C++類和對象【中】

&#x1f31f; 各位看官好&#xff0c;我是egoist2023&#xff01; &#x1f30d; 種一棵樹最好是十年前&#xff0c;其次是現在&#xff01; &#x1f680; 今天來學習C類和對象的語法知識。注意&#xff1a;在本章節中&#xff0c;小編會以Date類舉例 &#x1f44d; 如果覺得…

PgSql 操作技巧

1、查詢數據導出csv數據 \COPY (SELECT w.* from t_sys_warn w ) TO /home/cuadmin/warn_output.csv WITH CSV HEADER;2、導出sql Insert語句 pg_dump -U 用戶名 -h 主機名 -p 端口號 -d 數據庫名 --inserts -t 表名 > 導出文件.sqlpg_dump -U username -d dbname -t tabl…

Unity ES3保存類的問題

有以下一個物品類 public class Item_Base//基礎物品 { public string ID; private Attribute_Data Item_attribute new(); } 當使用ES3保存這個類時&#xff0c;Item_attribute的數據不會被保存&#xff0c;因為它是私有private ES3保存類時&#xff0c;只會保存…

react基本功

useLayoutEffect useLayoutEffect 用于在瀏覽器重新繪制屏幕之前同步執行代碼。它與 useEffect 相同,但執行時機不同。 主要特點 執行時機:useLayoutEffect 在 DOM 更新完成后同步執行,但在瀏覽器繪制之前。這使得它可以在瀏覽器渲染之前讀取和修改 DOM,避免視覺上的閃爍…

Spring Boot筆記(上)

01 概要 Spring Boot 是 Java 領域最流行的 快速開發框架&#xff0c;專為簡化 Spring 應用的初始搭建和開發而設計。 一、Spring Boot 解決了什么問題&#xff1f; 傳統 Spring 痛點 ? 繁瑣的 XML 配置 ? 需要手動管理依賴版本 ? 部署依賴外部 Web 服務器&#xff08;如 …

目標檢測YOLO實戰應用案例100講-基于毫米波雷達的多目標檢測 (續)

目錄 3.2 改進的CFAR目標檢測算法 3.3 算法步驟描述 3.4 實驗結果與分析 基于VGG16-Net的毫米波雷達目標檢測算法 4.1 VGG16-Net網絡模型 4.2 改進VGG16-Net網絡的目標檢測算法 4.3 算法步驟描述 4.4 實驗結果與分析 知識拓展 基于毫米波雷達的多目標檢測:使…

gitsubtree怎么添加新的子倉庫

要使用 git subtree 添加一個新的子倉庫&#xff0c;可以按照以下步驟操作&#xff1a; 1. 添加子倉庫 使用 git subtree add 命令將子倉庫的內容添加到主倉庫的指定目錄中。命令格式如下&#xff1a; git subtree add --prefix<子目錄路徑> <子倉庫地址> <子…

文本轉語音-音畫適時推送rtsp并播放

文本語音 rtsp適時播放叫號系統的底層邏輯 發布Linux, unix socket 和window win32做為音頻源的 python10下的(ffmpeg version 7.1) 可運行版本. 這兩天在弄這個&#xff0c;前2篇是通過虛擬聲卡&#xff0c;達到了最簡單的一個邏輯&#xff0c;播放文本就從聲卡發聲&#xff0…

從0開始的操作系統手搓教程33:掛載我們的文件系統

目錄 代碼實現 添加到初始化上 上電看現象 掛載分區可能是一些朋友不理解的——實際上掛載就是將我們的文件系統封裝好了的設備&#xff08;硬盤啊&#xff0c;SD卡啊&#xff0c;U盤啊等等&#xff09;&#xff0c;掛到我們的默認分區路徑下。這樣我們就能訪問到了&#xff…

【圖片批量轉換合并PDF】多個文件夾的圖片以文件夾為單位批量合并成一個PDF,基于wpf的實現方案

項目背景: 多個圖片分布在不同文件夾,如何以文件夾為單位批量合并成一個PDF,還要保證文件夾里面圖片大小和順序 實現功能: 1、單張圖片的轉換PDF:一張圖臨時轉一下 2、多張圖片轉換成PDF:多張圖單獨轉成PDF 3、多級目錄多張圖轉換成PDF:多級目錄多張圖單獨轉成多個PDF…

如何用Kimi生成PPT?秒出PPT更高效!

做PPT是不是總是讓你頭疼&#xff1f;&#x1f629; 快速制作出專業的PPT&#xff0c;今天我們要推薦兩款超級好用的AI工具——Kimi 和 秒出PPT&#xff01;我們來看看哪一款更適合你吧&#xff01;&#x1f680; &#x1f947; Kimi&#xff1a;讓PPT制作更輕松 Kimi的生成效…

從 MongoDB 到 TDengine,沃太能源實現 18 倍寫入性能提升

導讀 沃太能源是國內領先儲能設備生產廠商&#xff0c;數十萬儲能終端遍布世界各地。此前使用 MongoDB 存儲時序數據&#xff0c;但隨著設備測點增加&#xff0c;MongoDB 在存儲效率、寫入性能、查詢性能等方面暴露出短板。經過對比&#xff0c;沃太能源選擇了專業時序數據庫 …

數據庫基本建表操作

1.登錄數據庫并創建數據庫db_ck 創建完成后使用到我們創建的數據庫。 2.創建表t_hero 根據hero屬性包括&#xff08;id&#xff0c;name&#xff0c;nickname&#xff0c;age&#xff0c;gender&#xff0c;address&#xff0c;weapon&#xff0c;types&#xff09; 創建完…