優選算法的妙思之流:分治——快排專題

專欄:算法的魔法世界

個人主頁:手握風云

目錄

一、快速排序

二、例題講解

2.1.?顏色分類

2.2.?排序數組

2.3.?數組中的第K個最大元素

2.4.?庫存管理 III


一、快速排序

????????分治,簡單理解為“分而治之”,將一個大問題劃分為若干個子問題,直到這個子問題能夠快速解決。我們之前的快速排序是選出一個數作為基準值,然后將一個數組劃分為兩個子序列,一個序列<=基準值,另一個>基準值。但這種算法在數據特別大的時候是會超時的。所以我們這里要使用更優秀的三塊劃分和隨機選擇基準元素的算法。

二、例題講解

2.1.?顏色分類

? ? ? ? 這道題我們可以參照移動零里面的劃分策略。移動零里面是利用雙指針將數組分為0區域和非0區域,這道題我們也可以使用三個指針left、right、i來將其劃分為0、1、2區域。其中i用來遍歷數組,left用來標記0區域的最右側,right用來標記2區域的最左側。

? ? ? ? 接下來進行分類討論:如果nums[i]=0,我們讓nums[left+1]與nums[i]進行交換,然后i++,left++,就能保證[left+1,i-1]區間還都是1,還可能有一種極端情況,就是i=left+1,自身與自身進行交換,還是得需要left和i++,綜上我們就可以寫成nums[++left]與nums[i++]進行交換。如果nums[i]=1,我們直接就可以i++就可以。如果nums[i]=2時,right的移動也可以參照上面left的處理,--right,但i不能++,因為i右側是未遍歷的區間,如果i++,就會跳過這個元素。當i=right時,結束循環。

? ? ? ? 完整代碼實現:

class Solution {public void sortColors(int[] nums) {int left = -1, right = nums.length, i = 0;while (i < right) {if (nums[i] == 0)swap(nums, ++left, i++);else if (nums[i] == 1)i++;else if (nums[i] == 2)swap(nums, --right, i);}}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}
}

2.2.?排序數組

? ? ? ? 這道題如果我們直接采用之前的快排思想是會超時的,因為如果數組里的元素都等于基準值key,這樣數組元素就會跑到數組的最右側,導致時間復雜度會退化成O(n^{2})

? ? ? ? 我們接下來利用數組分三塊的思想,將其劃分為3個區域,<=key,=key,>=key。這樣當基準值都等于key時,時間復雜度直接降為O(n)

? ? ? ? 接下來就是如何隨機選擇基準值。我們需要在數組下標中等概率地選擇一個下標,那么我們就可以利用隨機數種子,利用公式r%(right-left+1)+left求出隨機下標。

? ? ? ? 完整代碼實現:

class Solution {public int[] sortArray(int[] nums) {Quicksort(nums, 0, nums.length - 1);return nums;}private void Quicksort(int[] nums, int l, int r) {if (l >= r) return;//作為遞歸結束的條件//數組分三塊int key = nums[new Random().nextInt(r - l + 1) + l];int left = l - 1, right = r + 1, i = l;while (i < right) {if (nums[i] < key) swap(nums, ++left, i++);else if (nums[i] == key) i++;else if (nums[i] > key) swap(nums, --right, i);}Quicksort(nums, l, left);Quicksort(nums, right, r);}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}
}

2.3.?數組中的第K個最大元素

? ? ? ? 因為這道題讓我們用時間復雜度為O(n),所以我們的思路很明顯要使用快速選擇排序,也就是上一題的數組分三塊與隨機選擇基準元素。那么這個第K大的元素就有可能落在三個區域內,我們設三個區域的元素個數分別為a、b、c。如果c>=k,那我們就直接去>key的這個區域去尋找;如果b+c>=k,就直接返回key;如果前兩個都不成立,就去<key這個區間去尋找第k-b-c大的元素。

? ? ? ? 完整代碼實現:

class Solution {public int findKthLargest(int[] nums, int k) {return Quicksort(nums, 0, nums.length - 1, k);}private int Quicksort(int[] nums, int l, int r, int k) {if (l == r) return nums[l];//隨機選擇基準元素int key = nums[new Random().nextInt(r - l + 1) + l];//根據基準元素,把數組分為三塊int left = l - 1, right = r + 1, i = l;while (i < right) {if (nums[i] < key) swap(nums, ++left, i++);else if (nums[i] == key) i++;else if (nums[i] > key) swap(nums, --right, i);}//分類討論//區間:[l,left],[left+1,right-1],[right,r]int b = right - left - 1, c = r - right + 1;if (c >= k) return Quicksort(nums, right, r, k);else if (b + c >= k) return key;else return Quicksort(nums, l, left, k - b - c);}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}
}

2.4.?庫存管理 III

? ? ? ? 題目就是求數組中的最小的cnt個數。第一種解法,可以使用Arrays.sort()方法來對數組進行排序,找出前k個元素;第二種解法,利用大根堆,創建一個大小為k的大根堆,將數組的前k個元素丟進大根堆中,然后再將數組剩余的元素與堆頂元素比較,如果小就交換并調整堆,最后堆里面就是最小的k個數;第三個解法,就是快速選擇算法。第一種解法的時間復雜度為NlogN,第二種解法的時間復雜度為Nlog(cnt),第三中解法的時間復雜度為N

? ? ? ? 按照上一題的思路,將數組分為三塊,三個區間內元素的個數分別為a、b、c。如果a>cnt,那么我們只需要去<key的區間去尋找;如果a+b>=cnt,此時的cnt一定是大于a的,那么最小的cnt個數,一定位于左側兩個區間,而中間區間又都是等于key的,所以不需要遞歸,直接++;如果前兩個都不成立,直接去最右側的區間去尋找第cnt-a-b個元素。

? ? ? ? 完整代碼實現:

class Solution {public int[] inventoryManagement(int[] stock, int cnt) {Quicksort(stock,0,stock.length - 1,cnt);int[] ret = new int[cnt];for (int i = 0; i < cnt; i++) {ret[i] = stock[i];}return ret;}private void Quicksort(int[] nums, int l, int r, int k) {if(l >= r) return;//隨機獲取基準元素int key = nums[new Random().nextInt(r - l + 1) + l];int left = l - 1,right = r + 1,i = l;//數組分三塊while(i < right){if(nums[i] < key) swap(nums,++left,i++);else if (nums[i] == key) i++;else if (nums[i] > key) swap(nums,--right,i);}//分類討論int a = left - l + 1,b = right - left - 1;if(a > k) Quicksort(nums,l,left,k);else if (a + b >= k) return;else Quicksort(nums,right,r,k - a - b);}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}
}

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

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

相關文章

二叉樹的ACM板子(自用)

package 二叉樹的中序遍歷;import java.util.*;// 定義二叉樹節點 class TreeNode {int val; // 節點值TreeNode left; // 左子節點TreeNode right; // 右子節點// 構造函數TreeNode(int x) {val x;} }public class DMain {// 構建二叉樹&#xff08;層序遍歷方式&…

Linux常用命令詳解:從基礎到進階

目錄 一、引言 二、文件處理相關命令 &#xff08;一&#xff09;grep指令 &#xff08;二&#xff09;zip/unzip指令 ?編輯 &#xff08;三&#xff09;tar指令 &#xff08;四&#xff09;find指令 三、系統管理相關命令 &#xff08;一&#xff09;shutdown指…

Qt多線程從基礎到性能優化

一、為什么需要多線程開發 現代應用程序的性能需求 CPU多核架構的有效利用 復雜任務的解耦與響應式界面保持 二、Qt線程創建四大方式 1. 繼承QThread重寫run() class WorkerThread : public QThread {void run() override {// 耗時操作qDebug() << "Thread ID…

【java】在 Java 中,獲取一個類的`Class`對象有多種方式

在 Java 中&#xff0c;獲取一個類的Class對象有多種方式。Class對象代表了 Java 中的一個類或接口的運行時類信息&#xff0c;可以用于反射操作。以下是獲取Class對象的幾種常見方法&#xff1a; 1.使用.class屬性 每個類都有一個.class屬性&#xff0c;可以直接獲取該類的Cl…

什么是RPC通信

RPC&#xff08;Remote Procedure Call&#xff0c;遠程過程調用&#xff09;通信是一種允許程序像調用本地函數一樣調用遠程服務器上函數的通信技術。它簡化了分布式系統中的網絡交互&#xff0c;隱藏了底層網絡通信的復雜性&#xff0c;使開發者能夠專注于業務邏輯。 一、RPC…

還是主題混合程序設計

以下是針對您現有代碼的完整主題化改造方案&#xff0c;實現跨QML/Qt Widgets的陰影主題系統&#xff1a; 一、主題管理系統核心 // thememanager.h #pragma once #include <QObject> #include <QColor> #include <QMap> #include <QQmlEngine>class…

BT-Basic函數之首字母T

BT-Basic函數之首字母T 文章目錄 BT-Basic函數之首字母Ttabtesttest conttest monitortest on boardstest scanworkstest shortstesthead cleanuptesthead configurationtesthead istesthead power on/offtesthead statustestjet print level istestordertestplan generationth…

7-9 趣味游戲

題目解析 在某個學校的趣味游戲活動中&#xff0c;N 名同學站成一排&#xff0c;他們的年齡恰好是 1 到 N &#xff0c;需要注意的是他們并不是按照年齡的大小排列的&#xff0c;而是隨機排列的。 游戲的規則是請同學們快速計算出&#xff0c;如果在這 N 名同學的小組中&…

Hugging Face模型微調訓練(基于BERT的中文評價情感分析)

文章目錄 學習視頻地址項目地址數據集的下載模型微調的基本概念與流程加載數據集數據集格式數據集信息 制作Dataset數據集字段數據集信息 vocab字典操作詞匯表文本轉換 下游任務模型設計模型訓練與保存數據加載優化器訓練循環 最終效果評估與測試模型加載和測試 學習視頻地址 …

【藍橋杯】十五屆省賽B組c++

目錄 前言 握手問題 分析 排列組合寫法 枚舉 小球反彈 分析 代碼 好數 分析 代碼 R 格式 分析 代碼 寶石組合 分析 代碼 數字接龍 分析 代碼 拔河 分析 代碼 總結 前言 主播這兩天做了一套藍橋杯的省賽題目&#xff08;切實感受到了自己有多菜&#x…

必刷算法100題之計算右側小于當前元素的個數

題目鏈接 315. 計算右側小于當前元素的 個數 - 力扣&#xff08;LeetCode&#xff09; 題目解析 計算數組里面所有元素右側比它小的數的個數, 并且組成一個數組,進行返回 算法原理 歸并解法(分治) 當前元素的后面, 有多少個比我小(降序) 我們要找到第一比左邊小的元素, 這…

Hyperlane框架:下一代高性能Rust Web框架 [特殊字符]

Hyperlane框架&#xff1a;下一代高性能Rust Web框架 &#x1f680; 引言 &#x1f44b; 在當今快速發展的Web開發領域&#xff0c;性能和開發效率的平衡變得越來越重要。Hyperlane作為一個新興的Rust Web框架&#xff0c;完美地解決了這個問題。本文將帶您深入了解Hyperlane…

圖像處理:使用Numpy和OpenCV實現傅里葉和逆傅里葉變換

文章目錄 1、什么是傅里葉變換及其基礎理論 1.1 傅里葉變換 1.2 基礎理論 2. Numpy 實現傅里葉和逆傅里葉變換 2.1 Numpy 實現傅里葉變換 2.2 實現逆傅里葉變換 2.3 高通濾波示例 3. OpenCV 實現傅里葉變換和逆傅里葉變換及低通濾波示例 3.1 OpenCV 實現傅里葉變換 3.2 實現逆傅…

OpenEuler/CentOS一鍵部署OpenGauss數據庫教程(腳本+視頻)

&#x1f4cc;OpenEuler/CentOS一鍵安裝OpenGauss數據庫教程 為什么需要OpenGauss一鍵安裝腳本&#xff1f; 手動部署OpenGauss數據庫時&#xff0c;環境適配、依賴沖突等問題常讓開發者頭疼。尤其對新人而言&#xff0c;官方文檔的配置步驟可能耗時數小時甚至引發未知報錯。 …

如何解決 Hive 在創建 MySQL 表時出現亂碼???的問題

1.問題描述 我們啟動Hive建立一個學生students表格 使用desc students;查看表格結構時 發現有出現亂碼的情況 2.解決方案 打開Hive安裝機器上面的MySQL 切換到Hive數據庫 執行以下命令修改字段注釋字符集 mysql -u root -p123456;use hive;alter table COLUMNS_V2 modify col…

自定義組件觸發餓了么表單校驗

餓了么的表單控件&#xff0c;如果存在自定義組件更改了值&#xff0c;例如在el-from中存在原生input組件很有可能沒法觸發表單校驗&#xff0c;下拉框或者彈框組件仍然是報紅邊框。 這是因為餓了么的輸入框或者下拉框更改值的時候會自動觸發表單校驗&#xff0c;但是封裝過后的…

架構思維:查詢分離 - 表數據量大查詢緩慢的優化方案

文章目錄 Pre引言案例何謂查詢分離&#xff1f;何種場景下使用查詢分離&#xff1f;查詢分離實現思路1. 如何觸發查詢分離&#xff1f;方式一&#xff1a; 修改業務代碼&#xff1a;在寫入常規數據后&#xff0c;同步建立查詢數據。方式二&#xff1a;修改業務代碼&#xff1a;…

Linux開發工具——make/makefile

&#x1f4dd;前言&#xff1a; 這篇文章我們來講講Linux開發工具——make/makefile&#xff1a; &#x1f3ac;個人簡介&#xff1a;努力學習ing &#x1f4cb;個人專欄&#xff1a;Linux &#x1f380;CSDN主頁 愚潤求學 &#x1f304;其他專欄&#xff1a;C學習筆記&#xf…

python加載訓練好的模型并進行葉片實例分割預測

要基于“GMT: Guided Mask Transformer for Leaf Instance Segmentation”進行代碼復現&#xff0c;可按照以下步驟利用Python實現&#xff1a; 環境配置 克隆倉庫&#xff1a;在終端中使用git clone https://github.com/vios-s/gmt-leaf-ins-seg.git命令&#xff0c;將項目代…

AI平臺初步規劃實現和想法

要實現一個類似Coze的工作流搭建引擎&#xff0c;可以結合SmartEngine作為后端工作流引擎&#xff0c;ReactFlow作為前端流程圖渲染工具&#xff0c;以及Ant Design作為UI組件庫。以下是實現的步驟和關鍵點&#xff1a; ### 1. 后端工作流引擎&#xff08;SmartEngine&#xf…