算法訓練營Day01(二分 雙指針)

704. 二分查找 - 力扣(LeetCode)

關于二分查找

  • 最重要的是要處理好邊界問題,每次寫完邊界可以帶入特殊值進行測試
  • 確定區間的不變量是什么?比如區間的左閉右閉,和左閉右開,每次二分完的新區間,一定要一直和最開始的區間的定義保持一致,要時刻明確區間的含義
  • 注意二分的幾種情況(當數組長度為n的情況下)
    • 當l = 0, r = n的時候因為r這個值我們在數組中無法取到,while(l < r) 是正確寫法
    • 當l = 0, r = n - 1的時候因為r這個值我們在數組中可以取到,while(l <= r) 是正確寫法 主要看能不能取到這個值
  • 注意處理二分mid溢出的問題
    • 當l 和 r 較大時,mid = (l + r) / 2 可能會出現大于INT_MAX的情況,會溢出。
    • 可以寫成 mid = l + (r - l) / 2? 或者 mid = l + ((r - l) >>1)的形式

思路:這道題目的前提是數組為有序數組,同時題目還強調數組中無重復元素,因為一旦有重復元素,使用二分查找法返回的元素下標可能不是唯一的,這些都是使用二分法的前提條件,當大家看到題目描述滿足如上條件的時候,可要想一想是不是可以用二分法了。

一開始的代碼:

class Solution {
public:int search(vector<int>& nums, int target) {int size = nums.size();int l = 0, r = size - 1;while(l < r){int mid = (l + r) >> 1;if(nums[mid] < target)l = mid+1;elser = mid;}if(nums[r] != target)return -1;return r;}
};

這個代碼可以解決數組中存在重復元素的情況,但是要注意的點有許多,第一個 l < r 當我寫成 l <= r 時會死循環,因為當r = l時,進去循環,會一直r = mid 不能跳出循環,導致死循環還是要注意,這可能是不規范的寫法吧。

下面有兩個規范的模版(只能用于嚴格的升序排序,不能出現相同的元素,如果目標元素出現多次就不能正確的返回下標

左閉右閉

class Solution {
public:int search(vector<int>& nums, int target) {int size = nums.size();int l = 0, r = size - 1;while(l <= r){int mid = l + ((r - l) >> 1);if(nums[mid] < target)//mid 小于就去mid的右面去找,并且mid不為targetl = mid+1;else if(nums[mid] > target)//mid 大于就去mid的左面去找,并且mid不為targetr = mid-1;else//就是 mid = target 的情況,所以直接返回mid就可以了return mid;}//沒有在循環中返回說明,沒有找到目標,返回-1return -1;}
};

左閉右開

class Solution {
public:int search(vector<int>& nums, int target) {int size = nums.size();int l = 0, r = size;while(l < r)    // r不能取到,l = r 沒有意義{int mid = l + ((r - l) >> 1);if(nums[mid] < target)//mid 小于就去mid的右面去找,并且mid不為targetl = mid+1;else if(nums[mid] > target)//mid 大于就去mid的左面去找,并且mid不為target,但是區間不包含mid 所以 r = midr = mid;else//就是 mid = target 的情況,所以直接返回mid就可以了return mid;}//沒有在循環中返回說明,沒有找到目標,返回-1return -1;}
};

其實二分還有很多應用場景,有著許多變體,比如說查找第一個大于target的元素或者第一個滿足條件的元素,都是一樣的,根據是否滿足題目的條件來縮小答案所在的區間,這個就是二分的本質。另外需要注意,二分的使用前提:有序數組

27. 移除元素 - 力扣(LeetCode)

?我的思路(對撞指針)

????????題目要求返回不等于val的個數和nums數組,我們只需要考慮返回數組前面的部分是不等于val的就可以,所以這道題的解法是雙指針(對撞的),現從前面開始,如果不等于就走,等于之后 右指針在走,右指針找到不等于val的數字,與左指針指向的數字互換

class Solution {
public:int removeElement(vector<int>& nums, int val) {int l = 0, r = nums.size()-1;//如果為空直接返回0if(l > r)   return 0;while(l < r){if(nums[l] != val)l++;else{if(nums[r] != val){int tmp = nums[r];nums[r] = nums[l];nums[l] = tmp;}r--;}}//循環出來一定是 l = r 再判斷 l=r時等不等于valif(nums[l] == val)  //因為返回的是個數return l ;elsereturn l+1;}
};

暴力解:

一開始要求暴力解第一時間還真沒想到,后來看到題解,才想到的暴力解。

?數組中元素不能刪除只能進行覆蓋,所以暴力的解法就是從前往后遍歷,找到val然后用后面的元素將val進行覆蓋,同時將nums數組的長度減減,最后返回記錄好的數組長度就可以了。

class Solution {
public:int removeElement(vector<int>& nums, int val) {int size = nums.size();for(int i = 0; i < size; i++){if(nums[i] == val){//val 后面的元素覆蓋val都向前進行覆蓋for(int j = i+1; j < size; j++){nums[j-1] = nums[j];}//交換之后,后面數組向前覆蓋,不知道后面數字是不是等于val然后要再一次判斷是不是等于vali--;//每覆蓋一次就要size--size--;}}return size;}
};

?雙指針(同向指針 \ 快慢指針)

快指針可以理解成在舊數組中找非目標元素,然后賦值給慢指針指向的新數組,雖然都指向一個數組

  • 關于二分法和移除元素的共性思考 這兩題之間有點類似的,他們都是在不斷縮小 left 和 right 之間的距離,每次需要判斷的都是 left 和 right 之間的數是否滿足特定條件。對于「移除元素」這個寫法本質上還可以理解為,我們拿 right 的元素也就是右邊的元素,去填補 left 元素也就是左邊的元素的坑,坑就是 left 從左到右遍歷過程中遇到的需要刪除的數,因為題目最后說超過數組長度的右邊的數可以不用理,所以其實我們的視角是以 left 為主,這樣想可能更直觀一點。用填補的思想的話可能會修改元素相對位置,這個也是題目所允許的。
  • ?fast < nums.size()fast <= nums.size()-1 沒什么區別,那為什么第二個會在空數組時報數組越界的錯誤? vector的size()函數返回值是無符號整數,空數組時返回了0,再減個一會溢出;變成一個很大的正數,nums[fast] 會發生 null pointer of type 'int' 異常。

雙指針法(快慢指針法):?通過一個快指針和慢指針在一個for循環下完成兩個for循環的工作。

雙指針法(快慢指針法)在數組和鏈表的操作中是非常常見的,很多考察數組、鏈表、字符串等操作的面試題,都使用雙指針法。

定義快慢指針

  • 快指針:尋找新數組的元素 ,新數組就是不含有目標元素的數組
  • 慢指針:指向更新 新數組下標的位置

所以思路就是,快指針在前面尋找不是目標元素的元素,慢指針可以理解為用來維護新數組,也就是不含目標元素的數組,如果不等于val 快慢指針都++,等于慢指針用來記錄val的位置,快指針向后尋找不等于val的值與慢指針的val進行交換,直到快指針走到最后

class Solution {
public:int removeElement(vector<int>& nums, int val) {int l = 0, r = 0;//r 每一步都要走for(int i = r; i < nums.size(); i++){//可以理解為,i為一個符合條件的數組,不等于val就往里面加if(nums[i] != val)nums[l++] = nums[i];}// l 就為新數組的長度return l;}
};

?977. 有序數組的平方 - 力扣(LeetCode)

思路:看到這道題,我首先想到的是,將他們的平方都放入數組中,然后進行排序,這種時間復雜度比較高的暴力解法。后面自己想了一下可不可以使用一個時間復雜度為O(1)的方法解出來呢,一開始想用雙指針,每個分別用來記錄一個數組,比較然后先比較在插入,發現最后回到了插入排序的思想。

先看看暴力解法

class Solution {
public:vector<int> sortedSquares(vector<int>& nums) {for(int i = 0; i < nums.size(); i++){nums[i] = nums[i]*nums[i];}sort(nums.begin(), nums.end());return nums;}
};

?可以發現雖然通過了,但是方法還是不太好。

雙指針

? ? ? ? 我們發現有負數和正數,我們不能判斷負數和正數誰的平方誰更大(為什么判斷誰更大呢,因為數組是從小到大排的,負數越小平方就越大,看到這,我們可不可以先開一個一摸一樣大小的數組,然后用兩個指針分別記錄數組兩端平方較大的值呢,誰更大誰就先從后往前插入)

class Solution {
public:vector<int> sortedSquares(vector<int>& nums) {int size =nums.size();int l = 0, r = nums.size()-1;//開一個新數組vector<int>a(nums.size());//x 用來為數組下標int x = size-1;while(l <= r){//右面大,右面賦值if(nums[l]*nums[l] < nums[r]*nums[r]){a[x--] = nums[r]*nums[r];r--;//指針向左移}    else{//左面大,左面賦值a[x--] = nums[l]*nums[l];//左指針右移l++;}}return a;}
};

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

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

相關文章

shadcn 使用步驟與注意點

目錄 一、shadcn ui 二、使用流程 1.安裝 2.顏色與主題 3.引用blocks 三、使用注意點 四、推薦搭配工具 五、總結 一、shadcn ui 官網&#xff1a;Build your component library - shadcn/ui 為何選擇它&#xff1f;因為它是一個基于 Tailwind CSS Radix UI 的組件集…

STM32CubeMX-H7-12-IIC讀寫MPU6050模塊(中)-MPU6050模塊詳解以及軟件IIC驅動

前言 上一篇我們已經完成對IIC代碼基本框架的編寫&#xff0c;以及獲取MPU6050的ID&#xff0c;接下來我們逐一分析這個模塊的功能&#xff0c;并用IIC驅動 建議看完上一篇再來看這篇 MPU6050寄存器介紹 1.電源管理寄存器&#xff08;PWR_MGMT_1&#xff0c;地址&#xff1a;0…

量子計算模擬中的GPU加速:從量子門操作到Shor算法實現

一、量子模擬的算力困境與GPU破局 量子計算模擬面臨?指數級增長的資源需求?&#xff1a;n個量子比特的態向量需要2^n個復數存儲空間。當n>30時&#xff0c;單機內存已無法承載&#xff08;1TB需求&#xff09;。傳統CPU模擬器&#xff08;如Qiskit的Aer&#xff09;在n28…

spring mvc 異常處理中@RestControllerAdvice 和 @ControllerAdvice 對比詳解

RestControllerAdvice 和 ControllerAdvice 對比詳解 1. 基本概念 注解等效組合核心作用ControllerAdviceComponent RequestMapping&#xff08;隱式&#xff09;定義全局控制器增強類&#xff0c;處理跨控制器的異常、數據綁定或全局響應邏輯。RestControllerAdviceControll…

JavaScript的回調函數:異步編程的基石

引言 在JavaScript的世界里&#xff0c;回調函數是一種強大而基礎的編程模式&#xff0c;它是異步編程的核心概念之一。隨著Web應用程序變得越來越復雜&#xff0c;理解和掌握回調函數變得尤為重要。本文將深入探討JavaScript回調函數的概念、應用場景以及最佳實踐。 什么是回…

測試用例 [軟件測試 基礎]

目錄 測試用例 1. 概念 1.1 什么是測試用例 1.2 什么是要素 1.3 為什么需要測試用例 2. 設計測試用例的萬能公式 2.1 常規思維 逆向思維 發散性思維 2.2 萬能公式 3. 設計測試用例的方法 3.1 基于需求的設計方法 3.2 具體的設計方法 3.3 更多用例練習 測試用例 …

Jupyter notebook定制字體

一、生成配置文件 運行Anaconda Powershell Prompt終端&#xff0c;輸入下面一行代碼&#xff1a; jupyter notebook --generate-config 將生成文件“C:\Users\XXX\.jupyter\jupyter_notebook_config.py”&#xff0c;XXX為計算機賬戶名字。 二、修改配置文件 c.NotebookAp…

miniconda安裝R語言圖文教程(詳細步驟)

本篇教程介紹,如何在Windows使用miniconda安裝R語言。 一、創建1個conda 虛擬環境 # 創建虛擬環境 conda create -n r_env # 激活虛擬環境 conda activate r_env二、安裝 R 語言 conda install -c r r-ggplot2三、運行測試 檢查安裝: 輸入 R 進入 R 的交互式命令行,檢查是…

【day1】AI軟件測試學習筆記

以下為整理的 AI軟件測試學習筆記&#xff0c;涵蓋性能測試工具鏈、AI大模型應用及開發實踐&#xff0c;分為四大模塊&#xff1a; 一、性能測試工具鏈與數據分析 1. 工具鏈整合效果 JMeter InfluxDB Grafana JMeter壓測數據存儲至云端InfluxDB&#xff0c;實現分布式壓測和…

WPF 資源加載問題:真是 XAML 的鍋嗎?

你的觀察很敏銳&#xff01;確實&#xff0c;在 WPF 項目中&#xff0c;.cs 文件主要負責邏輯實現&#xff0c;而資源加載的問題通常跟 XAML&#xff08;以及它背后的 .csproj 配置&#xff09;關系更大。我會圍繞這個觀點&#xff0c;用 CSDN 博客風格詳細解釋一下 .cs、XAML …

C++17模板編程與if constexpr深度解析

一、原理深化 1.1 模板編程 1.1.1 編譯器如何處理模板&#xff08;補充&#xff09; 模板的實例化機制存在兩種模式&#xff1a; 隱式實例化&#xff1a;編譯器在遇到模板具體使用時自動生成代碼&#xff0c;可能導致多翻譯單元重復實例化&#xff0c;增加編譯時間。顯式實…

408 計算機網絡 知識點記憶(6)

前言 本文基于王道考研課程與湖科大計算機網絡課程教學內容&#xff0c;系統梳理核心知識記憶點和框架&#xff0c;既為個人復習沉淀思考&#xff0c;亦希望能與同行者互助共進。&#xff08;PS&#xff1a;后續將持續迭代優化細節&#xff09; 往期內容 408 計算機網絡 知識…

MySQL學習筆記十四

第十六章創建高級聯結 16.1使用表別名 輸入&#xff1a; SELECT CONCAT(vend_name,(,RTRIM(vend_country),)) AS vend_title FROM vendors ORDER BY vend_name; 輸出&#xff1a; 輸入&#xff1a; SELECT cust_name, cust_contact FROM customers AS c, orders AS o, or…

Spring MVC 框架 的核心概念、組件關系及流程的詳細說明,并附表格總結

以下是 Spring MVC 框架 的核心概念、組件關系及流程的詳細說明&#xff0c;并附表格總結&#xff1a; 1. 核心理念 Spring MVC 是基于 MVC&#xff08;Model-View-Controller&#xff09;設計模式 的 Web 框架&#xff0c;其核心思想是 解耦&#xff1a; Model&#xff1a;數…

Android里藍牙使用流程以及問題詳解

一、基礎流程 請簡述 Android 藍牙開發的基本流程 1. 權限處理&#xff1a;動態申請藍牙和定位權限&#xff08;注意Android 12新權限&#xff09; 2. 初始化藍牙適配器&#xff1a;通過BluetoothManager獲取BluetoothAdapter 3. 設備發現&#xff1a;- 注冊BroadcastReceive…

OpenWrt 上安裝Tailscale

在 OpenWrt 上安裝 Tailscale 非常簡單&#xff0c;主要步驟如下&#xff1a; 1. 確保 OpenWrt 設備可聯網 首先&#xff0c;確保你的 OpenWrt 設備已經聯網&#xff0c;可以訪問外網&#xff0c;并且 SSH 進入你的路由器&#xff08;通常是 192.168.1.1&#xff09;&#xff…

藍橋杯刷題總結 + 應賽技巧

當各位小伙伴們看到這篇文章的時候想必藍橋杯也快開賽了&#xff0c;那么本篇文章博主就來總結一下一些藍橋杯的應賽技巧&#xff0c;那么依舊先來走個流程 那么接下來我們分成幾個板塊進行總結 首先是一些基本語法 編程語言的基本語法 首先是數組&#xff0c;在存數據的時候…

TCP重傳率高與傳輸延遲問題

目錄標題 排查步驟&#xff1a;TCP重傳率高與傳輸延遲問題v1.0通過 rate(node_netstat_Tcp_RetransSegs[3m]) 排查 TCP 重傳問題的步驟1. **指標含義與初步分析**2. **關聯指標排查**3. **定位具體問題源**4. **解決方案**5. **驗證與監控** v2.0一、基礎檢查二、網絡層分析三、…

【LeetCode 熱題100】73:矩陣置零(詳細解析)(Go語言版)

&#x1f680; 力扣熱題 73&#xff1a;矩陣置零&#xff08;詳解 多種解法&#xff09; &#x1f4cc; 題目描述 給定一個 m x n 的整數矩陣 matrix&#xff0c;如果一個元素為 0&#xff0c;則將其所在行和列的所有元素都設為 0。請你 原地 使用常量空間解決。 &#x1f3a…

組播網絡構建:IGMP、PIM 原理及應用實踐

IP組播基礎 組播基本架構 組播IP地址 一個組播IP地址并不是表示具體的某臺主機&#xff0c;而是一組主機的集合&#xff0c;主機聲明加入某組播組即標識自己需要接收目的地址為該組播地址的數據IP組播常見模型分為ASM模型和SSM模型ASM&#xff1a;成員接收任意源組播數據&…