【算法】時間復雜度以及O(N^2)的排序

目錄

1.常數時間的操作

2.時間復雜度

2.1.以選擇排序為例

2.2.O(n^2)從何而來

2.3.冒泡排序

2.3.1.抑或運算

2.4.插入排序

3.二分法

3.1.局部最小

4.遞歸

4.1.遞歸行為時間復雜度的估計


1.常數時間的操作

一個操作如果和樣本的數據量無關,每次都是固定時間內完成的操作,叫做常數操作

時間復雜度為一個算法流程中,常數數量的一個指標,常用O來表示。具體來說,先要對一個算法流程非常熟悉,然后去寫出這個算法流程中發生了多少次常數操作,進而總結出常數操作數量的表達式

在表達式中,只要高階項,不要低階項,也不要高階項的系數,剩下的部分如果為f(N),那么時間復雜度為O(f(N))

評價一個算法流程的好壞,先看時間復雜度的指標,然后再分析不同樣本數據下的實際運行時間,也就是“常數項時間”

  • 常數操作:int a = arr[i]; 或 +-*/ 或 位運算 等
  • 非常數操作:int b = 鏈表.get(i);

2.時間復雜度

2.1.以選擇排序為例

時間復雜度O(N^2),額外空間復雜度O(1)

設數組長度為N,我們遍歷N次,每次把遍歷到的最小值放在最左邊的位置上,同時把左邊界向右移動一位

我們每一次找出最小的數、次小的數、次次小的數...待尋找的區間不斷被壓縮

這是一種基礎且低效的查找方式,它的時間復雜度是O(n^2)

2.2.O(n^2)從何而來

數一數一共進行了多少次常數操作

第一次遍歷時,遍歷了N次,比較了N次,交換了1次

第二次遍歷時,遍歷了N-1次,比較了N-1次,交換了1次

......

遍歷:N + N-1 + N-2 + N-3 + ...

比較:N + N-1 + N-2 + N-3 + ...

swap:N次

三者相加 = aN^2 + bN + c只要高階項為N^2

2.3.冒泡排序

時間復雜度O(N^2),額外空間復雜度O(1)

相鄰兩個數字進行比較,大的數字往右移,一共遍歷N-1次,第一次從第1個元素開始與相鄰后一個元素比較,直到第N-1個元素與第N個元素比較完為止,此時當前數組中最大的元素一定被排序到了最后一位。接著繼續遍歷前N-1個元素,第二次遍歷結束后,前N-1個元素的最大值一定被排序到了倒數第二位...

public static void bubbleSort(int[] arr) {if (arr == null || arr.length < 2) {return;}for (int e = arr.length-1; e > 0; e--) {for (int i = 0; i < e; i++) {if (arr[i] > arr[i+1]) {swap(arr, i, i+1);}}}
}//交換arr的i和j位置上的值
public static void swap(int[] arr, int i, int j) {arr[i] = arr[i] ^ arr[j];arr[j] = arr[i] ^ arr[j];arr[i] = arr[i] ^ arr[j];
}
2.3.1.抑或運算

相同為0,不同為1

抑或運算還可以理解為無進位相加

  • 抑或運算的性質

(1) 0^N=N N^N=0

(2) 交換律:a^b = b^a

結合律:(a^b)^c = a^(b^c)

(3)同一批數進行抑或結果永遠相同

//怎么交換兩個數的值
a = a^b;
b = a^b; //即b = (a^b)^b = a^(b^b) = a^0 = a
a = a^b;

a和b的值可以相等,但這樣做的前提是a與b在內存里是兩塊獨立的區域,在數組中兩個指針所指向的位置不能相同

  • 與抑或有關的面試題

(1)

在一個數組中只有一種數出現了奇數次,其他的所有數都出現了偶數次,怎么找到出現了奇數次的數?要求時間復雜度O(N),空間復雜度O(1)

答:

int eor = 0;
for (int cur : arr) {eor ^= cur;
}
return eor;

(2) 在一個數組中只有兩種數出現了奇數次,其他的所有數都出現了偶數次,怎么找到出現了奇數次的數?要求時間復雜度O(N),空間復雜度O(1)

  • 為什么抑或運算滿足交換律與結合律

用“無進位相加”解釋:一組二進制數相加的結果與什么有關,與在某個二進制位上1的個數有關,與這些1出現的次序無關。在無進位相加時,偶數個1相加的結果是0,奇數個1相加的結果是1

//假設兩種出現奇數次的數是a、b,a!=b
int eor = 0;
for (int cur : arr) {eor ^= cur;
}
//eor == a^b != 0 => eor一定在某一位上等于1(int32位)
//假設eor的第x位為1
int eor_ = 0;
for (int cur : arr) {if (cur的第x位等于0) {eor_ ^= cur;}
}
//eor == a 或 eor == b 而另一個數則是eor^eor_

現在的問題是,eor的第幾位是1?

我們選擇最右側的1

//找到eor最右側的1
int rightOne = eor & (~eor + 1);
//cur的第x位為0這樣表示
cur & rightOne == 0;

2.4.插入排序

時間復雜度O(N^2),額外空間復雜度O(1)

一共排序N = arr.length次,第一次排序前1個數,第二次排序前2個數...每次都把當前范圍內最右邊的數向左移,直到左邊的數小于當前數字為止,此時該范圍內的數必定有序

???????

對于不同的數據,插入排序的時間復雜度不同

假如數據如下

時間復雜度為O(N^2)

假如數據如下

時間復雜度為O(N)

我們約定,時間復雜度是最壞情況下的算法表現,所以插入排序的時間復雜度是O(N^2)

public static void insertionSort(int[] arr) {if (arr == null || arr.length < 2) {return;}for (int i = 1; i < arr.length; i++) { //0~i做到有序for (int j = i-1; j >= 0 && arr[j] > arr[j+1]; j--) {swap(arr, j, j+1);}}
}
?
public static void swap(int[] arr, int i, int j) {arr[i] = arr[i] ^ arr[j];arr[j] = arr[i] ^ arr[j];arr[i] = arr[i] ^ arr[j];
}

3.二分法

一個有序數組找某個數是否存在

如果遍歷,算法時間復雜度O(N),沒有用到有序這一特性

我們每次將當前數組的中間位置元素與待查找元素比較,中間元素小,那就查找右側子數組,反之查找左側

每次查找都要“砍去”一半數組,數一數一共砍了幾次即可得到時間復雜度O(logN)

3.1.局部最小

無序也可以用二分

長度為N的數組,規定相鄰位置的元素一定不相等,如果0位置的數比1位置的數小,那么0位置的數是局部最小;如果N-1位置的數比N-2位置的數小,那么N-1位置的數為局部最小;對于中間位置i,如果i位置的數不僅比i-1位置的數小,而且比i+1位置的數小,那么i位置的數為局部最小。易得該數組必定存在至少一個局部最小

(1) 先看0位置的數是否小于1位置的數,若小則直接返回

(2) 看N-1位置的數是否小于N-2位置的數,若小則直接返回

(3) 我們取中點位置M,若[M] > [M-1],則向左側子數組查找;若[M] < [M-1]且[M] > [M+1],則向右側子數組查找;若都不滿足,則[M]為局部最小

4.遞歸

一道題引入遞歸

問:

找到一個數組的最大值

答:

不斷把當前數組拆成兩個子數組,返回兩個子數組的最大值中較大的那個

public static int getMax(int[] arr) {return process(arr, 0, arr.length-1);
}
?
public static int process(int[] arr, int L, int R) {if (L == R) {return arr[L];}int mid = L + ((R - l) >> 1);int leftMax = process(arr, L, mid);int rightMax = process(arr, mid+1, R);return Math.max(leftMax, rightMax);
}

對該數組進行遞歸

畫出它的遞歸結構圖

把遞歸的過程理解為一棵多叉樹,每一個節點都通過子節點為自己匯總信息之后才能繼續往上返回,棧空間就是整棵樹的高度

4.1.遞歸行為時間復雜度的估計

  • master公式

滿足子問題等規模的遞歸都可以用master公式求時間復雜度

T(N) = a*T(N/b) + O(N^d)

T(N)指的是母問題的數據量是N級別的

T(N/b)指的是子問題的規模都是N/b

a指的是子問題的調用次數

O(N^d)指的是除了調用子問題之外,剩下過程的時間復雜度

值得注意的是a/b未必等于1,因為以下式子同樣滿足master公式

T(N) = 2T(2N/3) + O(1)

結論:

logba < d ====> O(N^d)

logba > d ====> O(N^(logba))

logba == d ====> O((N^d)*logN)

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

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

相關文章

2021 年 3 月青少年軟編等考 C 語言五級真題解析

目錄 T1. 紅與黑思路分析T2. 密室逃脫思路分析T3. 求逆序對數思路分析T4. 最小新整數思路分析T1. 紅與黑 有一間長方形的房子,地上鋪了紅色、黑色兩種顏色的正方形瓷磚。你站在其中一塊黑色的瓷磚上,只能向相鄰的黑色瓷磚移動。請寫一個程序,計算你總共能夠到達多少塊黑色的…

C# 或 .NetCore 如何使用 NPOI 導出圖片到 Excel 文件

今天在本文中&#xff0c;我們將嘗試使用NPOI庫將圖像插入到 Excel 文件的特定位置。請將以下邏輯添加到您的寫作方法中&#xff0c;在 Excel 文件中添加圖像&#xff08;JPEG、PNG&#xff09;,我已經有一個示例 jpeg 文件 - Read-write-excel-npoi.jpg &#xff0c;我們將嘗試…

【學習筆記】理解深度學習的基礎:機器學習

1. 機器學習基礎 1.1 機器學習的定義與重要性 定義&#xff1a;深度學習是機器學習的一種特定形式。為了深入理解深度學習&#xff0c;必須牢固掌握機器學習的基本原理。機器學習算法是一種能夠從數據中學習的算法&#xff0c;通過經驗E在任務T上提高性能度量P&#xff08;Mi…

Observability:將 OpenTelemetry 添加到你的 Flask 應用程序

作者&#xff1a;來自 Elastic jessgarson 待辦事項列表可以幫助管理與假期計劃相關的所有購物和任務。使用 Flask&#xff0c;你可以輕松創建待辦事項列表應用程序&#xff0c;并使用 Elastic 作為遙測后端&#xff0c;通過 OpenTelemetry 對其進行監控。 Flask 是一個輕量級…

使用Matplotlib顯示中文的方法

1 問題提出 使用圖1所示的代碼進行matplotlib繪圖時&#xff0c;因為其默認不支持中文&#xff0c;此時無法顯示正確內容&#xff0c;如圖2所示。 圖1 matplotlib繪圖繪圖代碼 圖2 matplotlib無法顯示中文 2 問題解決 2.1 設置全局字體 在圖1所示的代碼中&#xff0c;第13…

詳解opencv resize之INTER_LINEAR和INTER_AREA

一。先簡單介紹一下resize的用法 src&#xff1a;輸入圖&#xff0c; dst&#xff1a;輸出圖 dsize&#xff1a;輸出圖的寬高&#xff0c;如果dsize不為空&#xff08;即寬高都不是0&#xff09;&#xff0c;則以dsize為準進行resize。 fx, fy是放大縮小的比例&#xff0c;是…

UnityDemo-TheBrave-制作筆記

這是我跟著b站up主MStudio的視頻學習制作的&#xff0c;大體上沒有去做一些更新的東西&#xff0c;這里只是一個總的總結。在文章的最后&#xff0c;我會放上可以游玩該游戲的鏈接和exe可執行文件&#xff0c;不過沒有對游戲內容進行什么加工&#xff0c;只有基本的功能實現罷了…

使用LSTM預測股票收盤價

在金融數據預測中&#xff0c;LSTM&#xff08;長短期記憶網絡&#xff09;憑借其在時間序列數據建模中的優勢&#xff0c;成為了分析股票價格趨勢的熱門選擇。本篇博客將以完整的代碼實現為例&#xff0c;展示如何利用LSTM網絡對股票收盤價進行預測&#xff0c;并從數據處理到…

模擬SpringIOCAOP

一、IOC容器 Ioc負責創建&#xff0c;管理實例&#xff0c;向使用者提供實例&#xff0c;ioc就像一個工廠一樣&#xff0c;稱之為Bean工廠 1.1 Bean工廠的作用 先分析一下Bean工廠應具備的行為 1、需要一個獲取實例的方法&#xff0c;根據一個參數獲取對應的實例 getBean(…

預編譯SQL

預編譯SQL 預編譯SQL是指在數據庫應用程序中&#xff0c;SQL語句在執行之前已經通過某種機制&#xff08;如預編譯器&#xff09;進行了解析、優化和準備&#xff0c;使得實際執行時可以直接使用優化后的執行計劃&#xff0c;而不需要每次都重新解析和編譯。這么說可能有一些抽…

Centos9 + Docker 安裝 MySQL8.4.0 + 定時備份數據庫到本地

Centos9 + Docker 安裝 MySQL8.4.0 + 定時備份數據庫到本地 創建目錄,創建配置文件啟動容器命令定時備份MySQL執行腳本Linux每日定時任務命令文件內參數其他時間參數AT一次性定時任務創建目錄,創建配置文件 $ mkdir -p /opt/mysql/conf$ vim /opt/mysql/conf/my.cnf[mysql] #…

軟件測試預備知識⑥—搭建Web服務器

在軟件測試的廣闊領域中&#xff0c;搭建Web服務器是一項極為關鍵的技能。它不僅有助于模擬真實的應用環境&#xff0c;方便我們對Web應用進行全面且深入的測試&#xff0c;還能讓測試人員更好地掌控測試場景&#xff0c;提升測試效率與質量。接下來&#xff0c;讓我們一同深入…

計算機視覺算法實戰——打電話行為檢測

?個人主頁歡迎您的訪問 ?期待您的三連 ? ?個人主頁歡迎您的訪問 ?期待您的三連 ? ?個人主頁歡迎您的訪問 ?期待您的三連? ??????? ??????????????? ?????? ? 1. 引言?? 隨著智能手機的普及&#xff0c;打電話行為檢測成為了計算機視…

事務的隔離級別和MDL

文章目錄 說明不同隔離級別可能發生的現象關鍵現象解釋MDL&#xff08;元數據鎖&#xff0c;Metadata Lock&#xff09;MDL 的作用MDL 的工作原理MDL 鎖的常見場景如何避免 MDL 阻塞 說明 本文章由大模型對話整理而來&#xff0c;如果有錯誤之處&#xff0c;請在評論區留言指正…

Linux第二課:LinuxC高級 學習記錄day01

0、大綱 0.1、Linux 軟件安裝&#xff0c;用戶管理&#xff0c;進程管理&#xff0c;shell 命令&#xff0c;硬鏈接和軟連接&#xff0c;解壓和壓縮&#xff0c;功能性語句&#xff0c;結構性語句&#xff0c;分文件&#xff0c;make工具&#xff0c;shell腳本 0.2、C高級 …

單片機存儲與計算機存儲:從微小到龐大的數據世界

單片機存儲與計算機存儲&#xff1a;從微小到龐大的數據世界 在現代電子設備中&#xff0c;存儲是至關重要的組成部分。無論是小巧的單片機&#xff0c;還是功能強大的計算機&#xff0c;存儲都扮演著不可或缺的角色。然而&#xff0c;單片機和計算機的存儲架構卻有著天壤之別…

ISP流程--去馬賽克詳解

前言 本期我們將深入討論ISP流程中的去馬賽克處理。我們熟知&#xff0c;彩色圖像由一個個像元組成&#xff0c;每個像元又由紅、綠、藍&#xff08;RGB&#xff09;三通道構成。而相機傳感器只能感知光的強度&#xff0c;無法直接感知光譜信息&#xff0c;即只有亮暗而沒有顏色…

阿里云-通義靈碼:在 PyCharm 中的強大助力(下)

目錄 六.通義靈碼在 PyCharm 中的優勢與不足 1.優勢 (1).提高開發效率 (2).提升代碼質量 (3).易于使用 (4).不斷學習和改進 2.不足 (1).依賴網絡 (2).準確性有待提高 (3).局限性 七.未來發展展望 1.提高準確性和可靠性 2.與其他工具的集成 3.智能化程度的提升 八…

開源項目stable-diffusion-webui部署及生成照片

參考鏈接 https://www.freedidi.com/13133.html 基礎環境部署 python 官網鏈接 Python Release Python 3.10.6 | Python.org 下載 Python 3.10.6 版本安裝包 下載好后雙擊 點擊安裝&#xff0c;這里需要選擇一下&#xff0c;把環境變量加上。&#xff08;這里是默認安裝到C盤…

【芯片封測學習專欄 -- 單 Die 與 多Die(Chiplet)介紹】

請閱讀【嵌入式開發學習必備專欄 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目錄 Overview單個Die&#xff08;Monolithic Die&#xff09;多個Die&#xff08;Chiplet Architecture or Heterogeneous SoC&#xff09;如何判斷一個SoC是…