【LeetCode】十、二分查找法:尋找峰值 + 二維矩陣的搜索

文章目錄

  • 1、二分查找法 Binary Search
  • 2、leetcode704:二分查找
  • 3、leetcode35:搜索插入位置
  • 4、leetcode162:尋找峰值
  • 5、leetcode74:搜索二維矩陣

1、二分查找法 Binary Search

找一個數,有序的情況下,直接遍歷找,時間復雜度為O(n),用二分法,一半一半的砍著找,則時間復雜度為O(log n),更優

在這里插入圖片描述

核心:左、中、右三個指針的移動

2、leetcode704:二分查找

在這里插入圖片描述

注意下面對中間指針的求法,不寫 (l + r ) / 2,寫成 l + (r - l) / 2,二者通分后值一樣,但l + r可能超出int的最大值,后者這種寫法則可規避這個問題。且 除二可以改為位運算 >> 1,其快于除法運算,注意右移的運算優先級很低,要加括號(a + b >> c 會首先執行加法 a + b,然后將結果右移 c 位

public class P704 {public static int binarySearch(int[] array, int value) {if (array == null || array.length == 0) {return 0;}int left = 0;int right = array.length - 1;int mid;while (left <= right) {mid = left + (right - left) / 2;if (array[mid] > value) {// 右邊半截不要了right = mid - 1;} else if (array[mid] < value) {// 左邊半截不要了left = mid + 1;} else {return mid;}}return -1;}
}

測試:

public class P704 {public static void main(String[] args) {int[] num = {-1, 0, 3, 5, 9, 12};System.out.println(binarySearch(num, 9));System.out.println(binarySearch(num, 10));}}

在這里插入圖片描述

3、leetcode35:搜索插入位置

在這里插入圖片描述
第一個想法是:先普通的二分查找value,返回-1后,說明不存在,那就再遍歷這個數組,用雙指針,當p1的值 < value && p2的值 > value時,return p1 + 1,但這樣應該是復雜了

在這里插入圖片描述

換個想法,只需調整下普通的二分查找:這題要求找值target,有就返回下標索引,無就返回插入后的下標索引,因此,這題要找第一個大于等于target的值的下標索引,如果有等于target的,那返回其下標,如果不存在,那就要插入到第一個比target大的值的位置,第一個大的值的下標則往后移動一位。

在這里插入圖片描述

public class P35 {public static int searchOrInsert(int[] array, int target) {if (array == null || array.length == 0) {return 0;}int left = 0;int right = array.length - 1;int ans = array.length;while (left <= right) {int mid = ((right - left) >> 1) + left;if (target == array[mid]) {// 如果有,直接返回return mid;} else if (target < array[mid]) {// 如果mid大于target,存一下mid的值// 此時mid是大于target的值,但不一定是第一個大于target的值ans = mid;right = mid - 1;} else {// 左指針右移,說明target很大,極限時,插入到末尾,此時return array.length即末尾left = mid + 1;}}return ans;}
}

4、leetcode162:尋找峰值

在這里插入圖片描述

一頭一尾是負無窮,所以,即使是1,2,3,4這個輸入,也有峰值:4

在這里插入圖片描述

m+1 > m時,m+1到right之間一定有一個峰值,不論m的左側是單增、單減、波浪起伏。此時可把左指針移動到m+1的位置,減少搜索范圍。

public class P162 {public static int getPeak(int[] array) {if (null == array || array.length == 0){return -1;}int left = 0;int right = array.length - 1;// 這兒不能允許left==right,否則當left=right=末尾元素時,mid也就是末尾元素,mid+1就越界了while (left < right) {int mid = left + ((right - left) >> 1);//說明mid和mid+1兩個點,從左到右是下降的,mid自身或者mid的左邊可能有峰值if (array[mid] > array[mid + 1]) {right = mid;} else {// 一定有個峰值出現在mid+1到right之間left = mid + 1;}}return left;}
}

5、leetcode74:搜索二維矩陣

如題,這樣特點的矩陣,本身就是遞增的,如圖中的1、3、5、7、10、11、16……

在這里插入圖片描述

在有序的集合里找一個數字,可以二分查找。但現在雖然有序,卻不是集合,是一個二維數組,那把矩陣拍平后就是一個簡單的二分查找了。把這個矩陣(二維數組)拍平有兩種思路:

  • 直接遍歷二維數組,把每個元素裝入一位數組,但這樣得兩層for,時間復雜度太高
  • 思想上拍平,將二維數組的索引,和一維數組建立聯系

考慮將二維數組的索引(x,y)轉為一維的索引i,。關于二維索引和一維索引的相互轉換,發現:

在這里插入圖片描述
將二維索引(x,y)和一維索引 i 標出來,得出:一維索引的坐標 i = x * 列總數 + y

如上面總列數為4(0,0)對應的一維坐標正好是 0 * 4 + 0 = 0

如此,不用遍歷二維數組,就可將矩陣的每個數都對應一個一維坐標。二分法時,起始左指針 = 0, 右指針 = 行數 × 列數 - 1(即總元素數),計算出mid后,無法根據mid索引在二維數組中取值,需要將一維坐標再倒回去,x = i / 列總數 ,y = i % 總列數

public class P74 {public boolean matrixSearch(int[][] matrix, int target) {if (null == matrix || matrix.length == 0) {return false;}// 行數int row = matrix.length;// 列數int col = matrix[0].length;// 左右指針起始位置int left = 0;int right = row * col - 1;while (left <= right) {int mid = left + (right - left) / 2;// 無法根據一維的mid索引在二維數組中取值,需要將一維坐標再倒回去// x = i / 列總數 ,y = i % 總列數int element = matrix[mid / col][mid % col];if (target == element) {return true;} else if (target < element) {right = mid - 1;} else {left = mid + 1;}}return false;}
}

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

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

相關文章

第4章:Electron主窗口與子窗口管理

4.1 創建主窗口 主窗口是 Electron 應用啟動后顯示的第一個窗口&#xff0c;通常用來承載應用的主界面。我們使用 BrowserWindow 類來創建主窗口。 4.1.1 創建主窗口的基礎代碼 // 引入 Electron 模塊和 Node.js 的 path 模塊 const { app, BrowserWindow } require(electr…

【動態規劃 前綴和】2478. 完美分割的方案數

本文涉及知識點 劃分型dp 動態規劃匯總 C算法&#xff1a;前綴和、前綴乘積、前綴異或的原理、源碼及測試用例 包括課程視頻 LeetCode 2478. 完美分割的方案數 給你一個字符串 s &#xff0c;每個字符是數字 ‘1’ 到 ‘9’ &#xff0c;再給你兩個整數 k 和 minLength 。 如…

【C++ Primer Plus學習記錄】指針和const

可以用兩種不同的方式將const關鍵字用于指針。第一種方法是讓指針指向一個常量對象&#xff0c;這樣就可以防止使用該指針來修改所指向的值&#xff0c;第二種方法是將指針本身聲明為常量&#xff0c;這樣可以防止改變指針指向的位置。 首先&#xff0c;聲明一個指向常量的指針…

前后端防重復提交(續)

前文介紹過前后端防重復提交的基本場景&#xff0c;簡單的情況是只發起一個異步請求&#xff0c;如果有多個異步請求怎么操作呢&#xff1f;這個要分情況看下。 如果是后端服務器的接口支持一次傳遞多個申請&#xff0c;那么可以將任務放進數組中&#xff0c;發往后端。這是最好…

074、Python 關于實例方法、靜態方法和類方法

在Python中&#xff0c;類可以定義三種類型的方法&#xff1a;實例方法、靜態方法和類方法。每種方法都有其特定的用途和調用方式。 實例方法&#xff08;Instance Methods&#xff09; 定義&#xff1a;實例方法是綁定到類實例上的方法。它們必須有一個名為self的隱式第一個參…

golang 1.22特性之for loop

背景 go1.22版本 for loop每輪循環都生成新的變量. 原諒: https://tip.golang.org/doc/go1.22 Previously, the variables declared by a “for” loop were created once and updated by each iteration. In Go 1.22, each iteration of the loop creates new variables, to …

【C++11】自己封裝RAII類,有哪些坑點?帶你了解移動語義的真相

文章目錄 一、持有資源的類定義移動構造函數的要點1.普通內置類型與std::move2.常見的容器與std::move3.結構體&#xff1a;4.智能指針與std::move 參考 一、持有資源的類定義移動構造函數的要點 1.普通內置類型與std::move 在C中&#xff0c;std::move 主要用于對象的移動語…

Wireshark - tshark支持iptables提供數據包

tshark現在的數據包獲取方式有兩種&#xff0c;分別是讀文件、網口監聽&#xff08;af-packet原始套接字&#xff09;。兩種方式在包獲取上&#xff0c;都是通過讀文件的形式&#xff1b;存在文件io操作&#xff0c;在專門處理大流量的情境下&#xff0c; 我們復用wireshark去做…

Windows編程上

Windows編程[上] 一、Windows API1.控制臺大小設置1.1 GetStdHandle1.2 SetConsoleWindowInfo1.3 SetConsoleScreenBufferSize1.4 SetConsoleTitle1.5 封裝為Innks 2.控制臺字體設置以及光標調整2.1 GetConsoleCursorInfo2.2 SetConsoleCursorPosition2.3 GetCurrentConsoleFon…

python如何輸出list

直接輸出list_a中的元素三種方法&#xff1a; list_a [1,2,3,313,1] 第一種 for i in range(len(list_a)):print(list_a[i]) 1 2 3 313 1 第二種 for i in list_a:print(i) 1 2 3 313 1 第三種&#xff0c;使用enumerate輸出list_a方法&#xff1a; for i&#xff0c;j in enum…

Redis的使用(二)redis的命令總結

1.概述 這一小節&#xff0c;我們主要來研究一下redis的五大類型的基本使用&#xff0c;數據類型如下&#xff1a; redis我們接下來看一看這八種類型的基本使用。我們可以在redis的官網查詢這些命令:Commands | Docs,同時我們也可以用help 數據類型查看命令的幫助文檔。 2. 常…

數據結構 - C/C++ - 串

字符處理 C 特性 C語言中字符串存儲在字符數組中&#xff0c;以空字符\0結束。 字符串常量&#xff0c;const char* str "Hello"&#xff0c;存儲在只讀的數據段中。 布局 字符串在內存中是字符連續存儲的集合&#xff0c;最后一個字符為空字符(ASCII值為0)&…

opencascade AIS_InteractiveContext源碼學習7 debug visualization

AIS_InteractiveContext 前言 交互上下文&#xff08;Interactive Context&#xff09;允許您在一個或多個視圖器中管理交互對象的圖形行為和選擇。類方法使這一操作非常透明。需要記住的是&#xff0c;對于已經被交互上下文識別的交互對象&#xff0c;必須使用上下文方法進行…

【問題已解決】Vue管理后臺,點擊登錄按鈕,會發起兩次網絡請求(竟然是vscode Compile Hero編譯插件導致的)

問題 VueElement UI 做的管理后臺&#xff0c;點擊登錄按鈕&#xff0c;發現 接口會連續掉兩次&#xff0c;發起兩次網絡請求&#xff0c;但其他接口都是正常調用的&#xff0c;沒有這個問題&#xff0c;并且登錄按鈕也加了loading&#xff0c;防止重復點擊&#xff0c;于是開…

搜索引擎常用語法

引號 (" "): 用雙引號將詞組括起來&#xff0c;搜索引擎將返回包含完全相同短語的結果。 示例&#xff1a;"人工智能發展趨勢" 減號 (-): 在關鍵詞前加上減號可以排除包含特定詞語的結果。 示例&#xff1a;人工智能 -機器學習&#xff08;排除包含 “機器…

樸素貝葉斯解密:sklearn中的分類器工作原理

&#x1f4da; 樸素貝葉斯解密&#xff1a;sklearn中的分類器工作原理 在機器學習領域&#xff0c;樸素貝葉斯分類器因其簡單、高效而廣受歡迎。特別是在處理大量特征數據時&#xff0c;樸素貝葉斯表現出了卓越的性能。scikit-learn&#xff08;簡稱sklearn&#xff09;是Pyth…

JavaMySQL 學習(基礎)

目錄 Java CMD Java發展 計算機存儲規則 Java學習 switch新用法&#xff08;可以當做if來使用&#xff09; 數組定義 隨機數 Java內存分配 MySQL MySQL概述 啟動和停止 客戶端連接 數據模型 關系型數據庫 SQL SQL通用語法 SQL分類 DDL--數據定義語言 數據庫…

瀏覽器開發者工具輔助爬蟲開發

文章目錄 瀏覽器開發者工具輔助爬蟲開發打開開發者工具使用Network面板分析請求數據示例步驟&#xff1a; 使用Elements面板查看和修改DOM結構示例步驟&#xff1a; 使用Console面板調試JavaScript代碼示例步驟&#xff1a;示例代碼&#xff1a;1. 輸出日志信息2. 輸出對象信息…

Vue 與 React 區別

Vue.js和React是現代Web開發中兩種非常流行的前端框架&#xff0c;兩者在**核心概念、組件以及生態系統擴展性**等方面存在區別。具體分析如下&#xff1a; 1. **核心概念** - **Vue**&#xff1a;Vue是一個漸進式JavaScript框架&#xff0c;它致力于視圖層&#xff0c;易于上手…

左值右值, 左值引用右值引用,完美轉發

一. 左值和右值 左值: 可以取地址的對象 右值: 不可以取地址的對象 double x1.0, y 2.0; 1; // 字面量, 不可取地址, 是右值 x y; // 表達式返回值, 不可取地址, 是右值 max(x, y); // 傳值返回函數的返回值 (非引用返回)總結就是: 根據是否可以取地址來區分是左值還…