【算法集訓】基礎算法:枚舉

一、基本理解

枚舉的概念就是把滿足題目條件的所有情況都列舉出來,然后一一判定,找到最優解的過程。
枚舉雖然看起來麻煩,但是有時效率上比排序高,也是一個不錯的方法、

二、最值問題

1、兩個數的最值問題

兩個數的最小值,利用C語言中的三元運算符就可以實現:

int Min(int a, int b) {
return a < b ? a : b;
}

2、n 個數的最值問題

當有 n 個數時 ai 時,我們可以首先取前兩個數,計算最小值;然后再拿這個最小值和第三個數去比較,得到的最小值再去和第四個數比較,以此類推,就可以計算出 n 個數中的最小值。
假設前 i 個數的最小值為 mi,則有遞推公式如下:

所以,把這個遞推公式翻譯成C語言,代碼是這樣的:

int Min(int a, int b) {
return a < b ? a : b;
}
int NMin(int* a, int n){
int *m = (int *) malloc( sizeof(int) * numsSize );
int m[0] = a[0];
for(int i = 1; i < n; ++i) {
m[i] = Min(m[i-1], a[i]);
}
int ret = m[n-1];
free(m);
return ret;
}

而這里的 m[i] 和 m[i-1] 可以利用迭代,存儲在一個變量中,用 C語言實現如下:

int Min(int a, int b) {
return a < b ? a : b;
}
int NMin(int* a, int n){
int m = a[0];
for(int i = 1; i < n; ++i) {
m = Min(m, a[i]);
}
return m;
}

3、最值問題的下標

當然,有些時候,我們求的并不是一個最小的數,要是要求出這個數組中,最小的數的下標,那么可以直接記錄下標,并且比較的時候直接通過下標去索引到值,然后進行比較,像這樣:
int NMin(int* a, int n){
int mIdx = 0;
for(int i = 1; i < n; ++i) {
if( a[i] < a[mIdx] ) {
mIdx = i;
}
}
return mIdx;
}
可以嘗試做一下這道題,鞏固一下概念:https://leetcode.cn/problems/maximum-sum-with-exactly-k-elements/

三、最值問題的進階

1、第三大的數

有時候,我們求最大的數不夠,想要求次大的,甚至第三大的,比如 1 2 2 3 中第三大的是 1 (相同的數只計算一次)。
這樣的問題,核心思路就是先把最大的求出來;然后忽略最大的數的情況下,再去求最大的;這時候就得到了次大的,再把次大的也忽略以后,再求最大的,自然就是第三大的了。
第三大的數 - 視頻講解。

2、數組中兩元素的最大乘積

要求找到數組中兩個元素的最大乘積,數組元素一定是正數。那么我們知道最大的兩個元素相乘一定是最大的,所以就是找最大的元素 和 次大的元素,但是這個問題和 第三大的數 略微有些不同,相同的數會被計算進去。
所以,我們找到最大的數以后,可以把它的下標忽略掉;然后再去找最大的數,這樣找到的一定是兩個可重復的最大元素和次大元素,將兩者相乘即可。
當然有同學就要問了,那我是不是直接把數組按照遞增排序,然后取最后兩個元素相乘就可以了。是的,也可以,但是比較排序的最優時間復雜度為 O(nlogn),而找兩次最大值的時間復雜度為 O(n)。

四、降維思想

一些統計類問題,第一個思路就是枚舉所有情況(也就是多個 for 循環),然后再去考慮是不是能夠把某些 for 循環的 O(n) 的時間復雜度降為 O(1),這個就是降維的思想。來看這個經典問題:
這個問題能自己想出來,就達到了 ACM 區域賽銅牌的水平。
給你一個長度為 n (n ≤ 4000) 下標從 0 開始的整數數組 nums ,它包含 1 到 n 的所有數字,請你返回上升四元組的數目。如果一個四元組 (i, j, k, l) 滿足以下條件,我們稱它是上升的:
1)0 <= i < j < k < l < n 且
2)nums[i] < nums[k] < nums[j] < nums[l] 。

1、O(n^4)

首先,最壞時間復雜度的算法,相信大家都能想出來,就是枚舉 i、j、k、l 四個變量,然后判斷 nums 四個數的關系,進行統計累加,這種情況下,最壞的時間復雜度為 O(n^4),由于 n 為 4000。
也就是相當于 n = 16000000 的數據量下,用 O(n^2) 的算法去求解問題,所以必然超時。

2、O(n^3)

如果要用 O(n^3) 的算法求解,你會怎么去思考呢?如果有想法,可以寫好以后附在評論區。

3、O(n^2)

是的,由于 n 的范圍限制, 就算你想出了 O(n^3) 的算法,還是過不了這個問題,我們需要繼續想 O(n^2) 的算法。
算法思路如下:
1、首先,我們枚舉 j 和 k,然后對所有滿足 nums[j] > nums[k] 的下標對,執行下一步。
2、那么只要我們找到數組下標為 0 到 j-1 的數中,小于 nums[k] 的個數,記為 a(也就是所有滿足條件的 i); 找到數組下標為 k+1 到 n-1 的數中,大于 nums[j] 的個數,記為 b(也就是所有滿足條件的); 將 a * b 就是所有滿足條件的 (i, l) 對,把所有的 (i, l) 數對累加,就是我們最后要求的答案了。
3、于是問題轉變成了求 找到數組下標為 0 到 j-1 的數中,小于 nums[k] 的個數 和 找到數組下標為 k+1 到 n-1 的數中,大于 nums[j] 的個數;
4、定義兩個輔助數組 less[4001][4001] 和 bigger[4001][4001],令 less[i][j] 表示前 i-1 個數中,小于 j 的數的個數;令 bigger[i][j] 表示 i 以后(不包括 i)的數中,大于 j 的數的個數。less 和 bigger 的含義類似,通過兩個 for 循環 枚舉求出 less 和 bigger。
5、最后,只要枚舉 j 和 k,在滿足 nums[j] > nums[k] 的條件下,累加 less[j][ nums[k] * bigger[k][nums[j]] 的和,就是我們要求的解了。

五、題目練習

2656. K 個元素的最大和

int maximizeSum(int* nums, int numsSize, int k){int max = 0;for(int i = 0; i < numsSize; ++i) {if(nums[i] > max) {max = nums[i];}}int ans = max;while(--k) {ans += max + 1;max += 1;}return ans;
}

414. 第三大的數

#define INF -213214121int thirdMax(int* nums, int numsSize){// 找最大值int max = nums[0];for(int i = 1; i < numsSize; ++i) {if(max < nums[i]) {max = nums[i];}}// 找第二大的數int subMax = INF;for(int i = 0; i < numsSize; ++i) {if(subMax == INF) {if(nums[i] < max) subMax = nums[i];}else {if(nums[i] > subMax && nums[i] < max) {subMax = nums[i];}}}//不存在第二大的,返回第一大的if(subMax == INF) return max;//找第三大的數int triMax = INF;for(int i = 0; i < numsSize; ++i) {if(triMax == INF) {if(nums[i] < subMax) triMax = nums[i];}else {if(nums[i] > triMax && nums[i] < subMax) {triMax = nums[i];}}}if(triMax == INF) return max;return triMax;
}

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

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

相關文章

Vscode安裝,ssh插件與配置

原因 發現很多新人在練習linux&#xff0c;可是只有windows機的時候&#xff0c;一般都是下載虛擬機&#xff0c;然后在虛擬機上安裝ubuntu等linux平臺。每次需要在linux中寫代碼&#xff0c;就打開ubuntu&#xff0c;然后在終端上用vim寫代碼&#xff0c;或者先編輯代碼文本&…

css實現上下左右居中

css實現子盒子在父級盒子中上下左右居中 幾種常用的上下左右居中方式 HTML代碼部分 <div class"box"><img src"./img/77.jpeg" alt"" class"img"> </div>css部分 方式一 利用子絕父相和margin:auto實現 <sty…

內存管理 -----分段分頁

分段 分段&#xff1a;程序的分段地址空間&#xff0c;分段尋址方案 兩個問題 分段 &#xff1a;是更好分離和共享 左邊是有序的邏輯地址&#xff0c;右邊是無序的物理地址&#xff0c;然后需要有一種映射的關系&#xff08;段關聯機制&#xff09; 各個程序的分配相應的地址…

Gin入門指南:從零開始快速掌握Go Web框架Gin

官網:https://gin-gonic.com/ GitHub:https://github.com/gin-gonic 了解 Gin Gin 是一個使用 Go 語言開發的 Web 框架,它非常輕量級且具有高性能。Gin 提供了快速構建 Web 應用程序所需的基本功能和豐富的中間件支持。 以下是 Gin 框架的一些特點和功能: 快速而高效:…

【簡說八股】面試官:你知道什么是IOC么?

回答 Spring的IOC&#xff08;Inversion of Control&#xff0c;控制反轉&#xff09;是Spring框架的核心特性之一。它通過將對象的創建和依賴關系的管理交給Spring容器來實現&#xff0c;降低了組件之間的耦合性&#xff0c;使得代碼更加靈活、可維護。 在傳統的開發模式中&…

Sora模型風口,普通人如何抓住-最新AI系統ChatGPT網站源碼,AI繪畫系統

一、前言說明 PandaAi創作系統是基于ChatGPT進行開發的Ai智能問答系統和Midjourney繪畫系統&#xff0c;支持OpenAI-GPT全模型國內AI全模型。本期針對源碼系統整體測試下來非常完美&#xff0c;那么如何搭建部署AI創作ChatGPT&#xff1f;小編這里寫一個詳細圖文教程吧。已支持…

邊緣計算與任務卸載基礎知識

目錄 邊緣計算簡介任務卸載簡介參考文獻 邊緣計算簡介 邊緣計算是指利用靠近數據生成的網絡邊緣側的設備&#xff08;如移動設備、基站、邊緣服務器、邊緣云等&#xff09;的計算能力和存儲能力&#xff0c;使得數據和任務能夠就近得到處理和執行。 一個典型的邊緣計算系統為…

前端按鈕動畫

效果示例 代碼示例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevic…

OSCP靶場--Resourced

OSCP靶場–Resourced 考點(1.rpc枚舉 2.crackmapexec密碼噴灑&#xff0c;hash噴灑 3.ntds.dit system提取域hash 4.基于資源的約束委派攻擊rbcd) 1.nmap掃描 ## ┌──(root?kali)-[~/Desktop] └─# nmap -sV -sC -p- 192.168.188.175 --min-rate 2000 Starting Nmap 7.9…

《一篇文章搞懂git(保姆級教學)》

目錄 1.版本管理工具概念 2. 版本管理工具介紹 2.1版本管理發展簡史(維基百科) 2.1.1 SVN(SubVersion) 2.1.2 Git 3. Git 發展簡史 4. Git 的安裝 4.1 git 的下載 ?4.2 安裝 5. Git 工作流程 5.1 Git 初始化 5.2 git 流程 5.2.1 流程圖 5.2.2概念即詳解 6.Git …

IO多路復用:提高網絡應用性能的利器

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》 &#x1f35a; 藍橋云課簽約作者、上架課程《Vue.js 和 E…

模型部署 - onnx的導出和分析 -(2) - onnx 注冊自定義算子 - 學習記錄

onnx 注冊自定義算子 第一步&#xff1a;手寫一個算子&#xff0c;然后注冊一下第二步&#xff1a;將算子放進模型定義第三步&#xff1a;利用 torch.onnx.export() 編寫onnx 導出函數 一般我們自定義算子的時候&#xff0c;有以下流程 編寫算子并注冊將算子放進模型定義利用 …

unity學習(46)——服務器三次注冊限制以及數據庫化角色信息1--數據流程

1.先找到服務器創建角色信息代碼的位置&#xff0c;UserBizImpl.cs中&#xff1a; public PlayerModel create(string accId, string name, int job) {PlayerModel[] playerModelArray this.list(accId);//list是個自建函數&#xff0c;本質通過accId來查詢if (playerModelAr…

ClickHouse數據引擎

ClickHouse 提供了多種索引引擎&#xff0c;每種引擎都有其特定的用途和特性。除了 MergeTree 引擎之外&#xff0c;以下是一些常見的索引引擎及其區別&#xff1a; MergeTree 引擎&#xff1a; 特點&#xff1a;有序、分布式、支持并發寫入和讀取。適用場景&#xff1a;適用于…

【高數】常數項級數概念與性質

下面為個人數學筆記&#xff0c;有需要借鑒即可。 一、常數項級數概念 二、常數項級數性質 三、調和級數 完。

備忘錄模式(Memento Pattern)

定義 備忘錄模式&#xff08;Memento Pattern&#xff09;是一種行為設計模式&#xff0c;它允許在不破壞封裝性的前提下捕獲一個對象的內部狀態&#xff0c;并在以后將對象恢復到該狀態。備忘錄模式通常用于實現撤銷操作&#xff08;Undo&#xff09;或歷史記錄&#xff08;H…

藍橋杯(3.3)

1208. 翻硬幣 import java.util.Scanner;public class Main {public static void turn(char[] a,int i) {if(a[i] *) a[i] o;else a[i] *;}public static void main(String[] args) {Scanner sc new Scanner(System.in);char[] a sc.next().toCharArray();char[] b sc.n…

python如何設置虛擬環境|方法有哪幾種

原文連接&#xff1a; python設置虛擬環境- Python學習導航 為什么需要虛擬環境&#xff1f; 在使用Python語言時&#xff0c;通過pip&#xff08;pip3&#xff09;來安裝第三方包&#xff0c;但是由于pip的特性&#xff0c;系統中只能安裝每個包的一個版本。但是在實際項目開…

c++之旅——第三彈

大家好啊&#xff0c;這里是c之旅第三彈&#xff0c;跟隨我的步伐來開始這一篇的學習吧&#xff01; 如果有知識性錯誤&#xff0c;歡迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 創作不易&#xff0c;希望大家多多支持哦&#xff01; 一.命名空間;…

項目設計:基于Qt和百度AI的車牌識別系統(嵌入式ARM)

基于Qt和百度AI智能云實現的智能車牌識別系統&#xff0c;具體可實現為停車場管理系統、智能計費停車系統…等。 1.系統實現思路及框架 1.1實現思路 要實現一個車牌識別系統&#xff0c;有多種方法&#xff0c;例如用opencv圖像算法實現&#xff0c;或用第三方算法接口&#x…