LeetCode 278. 第一個錯誤的版本

LeetCode 278. 第一個錯誤的版本 解析

這個問題要求找到第一個錯誤的版本,其中給定一個 API isBadVersion(version) 可以判斷某個版本是否錯誤。由于版本號是有序的,且錯誤版本之后的所有版本都是錯誤的,因此可以使用二分查找高效地定位第一個錯誤版本。

方法思路

  1. 二分查找框架
    初始化左右指針 leftright 分別指向第一個和最后一個版本。
    在每次循環中,計算中間版本 mid,并調用 isBadVersion(mid) 判斷:

    • mid 是錯誤版本,說明第一個錯誤版本在 mid 或其左側,更新 right = mid
    • mid 不是錯誤版本,說明第一個錯誤版本在 mid 右側,更新 left = mid + 1
  2. 終止條件
    leftright 相遇時,循環結束,此時 left 即為第一個錯誤版本。

C++ 代碼實現

// The API isBadVersion is already defined for you.
// bool isBadVersion(int version);class Solution {
public:int firstBadVersion(int n) {int left = 1;int right = n;while (left < right) {int mid = left + (right - left) / 2;  // 防止整數溢出if (isBadVersion(mid)) {right = mid;  // 錯誤版本在 mid 或其左側} else {left = mid + 1;  // 錯誤版本在 mid 右側}}return left;  // 循環結束時,left 即為第一個錯誤版本}
};

代碼解釋

  1. 二分查找初始化
    left = 1right = n 分別表示版本范圍的左右邊界。

  2. 防止整數溢出
    使用 mid = left + (right - left) / 2 代替 mid = (left + right) / 2,避免當 leftright 都很大時發生整數溢出。

  3. 循環條件
    while (left < right) 確保循環在 leftright 相遇時終止。

  4. 條件判斷

    • isBadVersion(mid) 為真,說明第一個錯誤版本在 [left, mid] 范圍內,更新 right = mid
    • 若為假,說明第一個錯誤版本在 [mid+1, right] 范圍內,更新 left = mid + 1
  5. 返回結果
    循環結束時,leftright 指向同一個位置,即第一個錯誤版本。

復雜度分析

  • 時間復雜度:O(log n),每次迭代將搜索范圍縮小一半。
  • 空間復雜度:O(1),只需要常數級額外空間。

示例

假設 n = 5,且第一個錯誤版本是 4
二分查找過程如下:

  1. 初始left = 1, right = 5, mid = 3
    • isBadVersion(3) 返回 falseleft = 4
  2. 第二次迭代left = 4, right = 5, mid = 4
    • isBadVersion(4) 返回 trueright = 4
  3. 終止條件left == right == 4,返回 4

關鍵點

  1. 二分查找變體
    與傳統二分查找不同,這里的 right 指向錯誤版本,因此更新時直接將 right = mid,而非 mid - 1

  2. 防止溢出
    使用 left + (right - left) / 2 計算中間值,避免整數溢出。

  3. 循環終止條件
    left < right 確保不會陷入死循環,且最終 left 即為所求結果。

這種方法高效且簡潔,是解決有序數組中查找特定元素問題的經典思路。

在二分查找解決“第一個錯誤版本”問題時,while (left < right) 循環的設計是為了精準收縮搜索范圍,最終讓 leftright 相遇在目標位置(第一個錯誤版本)。以下從邏輯推導和實例驗證兩方面詳細解釋:

核心邏輯:范圍收縮的必然性

二分查找的本質是通過不斷排除不可能的范圍,最終將搜索范圍縮小到唯一解。在“第一個錯誤版本”問題中:

  1. 范圍的單調性
    題目明確“錯誤版本之后的所有版本都是錯誤的”,即版本序列具有單調性:
    [正確版本, 正確版本, ..., 第一個錯誤版本, 錯誤版本, ..., 錯誤版本]
    這種單調性保證了二分查找的可行性。

  2. 循環條件 left < right 的作用

    • left < right 時,搜索范圍至少包含兩個版本,需要繼續收縮。
    • left == right 時,搜索范圍僅剩一個版本,這個版本必然是“第一個錯誤版本”(因為范圍收縮過程中已排除所有不可能的選項),循環終止。

范圍收縮的細節

在循環中,通過 isBadVersion(mid) 的結果調整 leftright,確保每次收縮都嚴格包含目標位置

  • isBadVersion(mid) == true
    mid 是錯誤版本,說明“第一個錯誤版本”可能是 mid 或在 mid 左側(因為左側可能有更早的錯誤版本)。因此收縮右邊界:right = mid

  • isBadVersion(mid) == false
    mid 是正確版本,說明“第一個錯誤版本”必然在 mid 右側(因為 mid 及左側都是正確的)。因此收縮左邊界:left = mid + 1

為什么必然相遇在目標位置?

假設目標位置為 ans(第一個錯誤版本),證明過程如下:

  1. 初始范圍left = 1right = n,顯然 ans[left, right] 內。
  2. 每次收縮后
    • mid 是錯誤版本(mid >= ans),則 right = mid,新范圍 [left, right] 仍包含 ans(因為 ans <= mid = right)。
    • mid 是正確版本(mid < ans),則 left = mid + 1,新范圍 [left, right] 仍包含 ans(因為 ans > mid = left - 1)。
  3. 范圍大小的變化
    每次循環后,范圍 [left, right] 的大小嚴格減小(至少減少 1),因此最終會收縮到 left == right
  4. 終止時的位置
    由于每次收縮都包含 ans,最終 left == right 時,這個位置必然是 ans

實例驗證

n = 5,第一個錯誤版本 ans = 4 為例:

步驟leftrightmid = left + (right-left)/2isBadVersion(mid)調整后范圍
1153false(正確版本)left = 4,范圍 [4,5]
2454true(錯誤版本)right = 4,范圍 [4,4]
344循環終止(left == right)-結果為 4

可見,最終 leftright 相遇在 4,即目標位置。

總結

while (left < right) 的循環設計通過單調收縮范圍,確保每次調整都不遺漏目標位置,最終讓 leftright 必然相遇在“第一個錯誤版本”。這種邏輯適用于所有有序且存在唯一解的二分查找問題,是二分查找的經典應用。

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

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

相關文章

【RK3568+PG2L50H開發板實驗例程】FPGA部分 | Pango 的時鐘資源——鎖相環

本原創文章由深圳市小眼睛科技有限公司創作&#xff0c;版權歸本公司所有&#xff0c;如需轉載&#xff0c;需授權并注明出處&#xff08;www.meyesemi.com) 1.實驗簡介 實驗目的&#xff1a; 了解 PLL IP 的基本使用方法。 實驗環境&#xff1a; Window11 PDS2022.2-SP6.4…

Graph Contrastive Learning with Generative Adversarial Network基于生成對抗網絡的圖對比學習

1. 什么是圖&#xff1f;&#xff08;Graph&#xff09;想象一下社交網絡&#xff0c;每個人是一個“點”&#xff08;節點&#xff09;&#xff0c;他們之間的朋友關系是“線”&#xff08;邊&#xff09;。這樣的點和線組成的結構就是“圖”。在計算機科學中&#xff0c;圖被…

PyTorch中的torch.argmax()和torch.max()區別

在PyTorch中&#xff0c;torch.argmax()和torch.max()都是針對張量操作的函數&#xff0c;但它們的核心區別在于返回值的類型和用途&#xff1a;1. torch.argmax() 作用&#xff1a;僅返回張量中最大值所在的索引位置&#xff08;下標&#xff09;。返回值&#xff1a;一個整數…

WebSocket主從服務器架構完整教程

目錄 1. 前言:為什么要學習WebSocket主從架構 第一章:基礎知識準備 2.1 什么是WebSocket 生活中的例子 技術特點 2.2 WebSocket vs HTTP 什么時候用WebSocket? 2.3 什么是主從架構 生活中的例子 技術架構圖 2.4 環境準備 需要的軟件 項目結構 第二章:WebSock…

Java的extends通配符

在Java泛型中&#xff0c;extends通配符用于限定泛型類型的上界&#xff0c;即指定泛型可以是某個類型或其子類型。它有兩種常見用法&#xff1a;類型參數限定和通配符限定&#xff0c;下面詳細介紹&#xff1a; 1. 類型參數限定&#xff08;在類/方法定義中&#xff09; 在定義…

vue自定義提示框組件

不想要elementui的消息提示&#xff0c;自定義一個組件系統統一使用 一、寫頁面 vue &#xff08;我放的目錄是src/plugins/message.vue&#xff09;&#xff08;這里面使用elementui 里面icon 需要單獨引入&#xff09; <template><Transition name"down"&…

自動駕駛數據集綜述:統計特征、標注質量與未來展望

自動駕駛數據集綜述&#xff1a;統計特征、標注質量與未來展望 A Survey on Autonomous Driving Datasets: Statistics, Annotation Quality, and a Future Outlook 得益于硬件和深度學習技術的快速進步&#xff0c;自動駕駛近年來迅速發展并展現出良好的性能。高質量的數據集…

redis數據結構和數據類型

1.動態字符串SIMPLE DYNAMIC STRING(SDS)觀察上圖中的SDS結構&#xff0c;頭部包含字符串長度和分配的空間&#xff0c;可以以O&#xff08;1&#xff09;的時間復雜度計算出字符串長度&#xff0c;并且有了字符串長度后可以無視c語言的字符串缺陷&#xff08;\0作為結尾標識&a…

深度學習--神經網絡

一、深度學習的簡單概念深度學習是一種模仿人類大腦的運行方式&#xff0c;從大量數據中學習特征的學習模式。深度學習是機器學習的子集&#xff0c;它與機器學習的關系如下&#xff1a;二、感知神經網絡2.1簡單定義神經網絡&#xff08;Neural Networks&#xff09;是一種模擬…

.NET 程序的強名稱簽名與安全防護技術干貨

在 .NET 開發領域&#xff0c;保障程序的安全性和完整性至關重要。強名稱簽名和有效的安全防護措施是實現這一目標的關鍵手段。下面將詳細介紹 .NET 程序的強名稱簽名以及相關的安全防護方法。一、什么是強名稱簽名強名稱簽名是 .NET 框架提供的一種安全機制&#xff0c;其主要…

DNS(Domain Name System,域名系統)

目錄 **一、DNS的核心功能****二、DNS的工作原理****1. 解析流程(以車載導航請求為例)****2. 關鍵機制****三、車載以太網中DNS的特殊性**1. **高可靠性要求**2. **低延遲優化**3. **安全挑戰與防護****四、DNS相關協議與技術****五、車載DNS配置示例****六、DNS故障排查工具…

優化 ECharts 多條折線:折線數據不完整導致的X軸日期錯亂問題

目錄 一、簡單介紹 1.1 常見類型 二、時間軸錯亂問題 2.1 示例 2.2 示例完整代碼 2.3 問題分析 2.4 修復方法 第一步 第二步 2.5 優化后完整代碼 一、簡單介紹 ECharts 是一款基于 JavaScript 的數據可視化圖表庫&#xff0c;動態圖表是 ECharts 的一個重要應用場景…

網絡安全之注入攻擊:原理、危害與防御之道

網絡安全之注入攻擊&#xff1a;原理、危害與防御之道 引言 在OWASP Top 10安全風險榜單中&#xff0c;注入攻擊常年占據首位。2023年Verizon數據泄露調查報告顯示&#xff0c;67%的Web應用漏洞與注入類攻擊直接相關。本文從技術視角系統解析注入攻擊的核心原理、典型場景及防御…

Python爬蟲動態IP代理報錯全解析:從問題定位到實戰優化

目錄 一、代理IP失效&#xff1a;爬蟲的"隱形殺手" 1.1 失效場景復現 1.2 解決方案 二、403封禁&#xff1a;反爬機制的"精準打擊" 2.1 封禁原理剖析 2.2 破解方案 三、速度瓶頸&#xff1a;代理性能的"致命短板" 3.1 性能對比測試 3.2…

機器學習基礎知識【 激活函數、損失函數、優化器、 正則化、調度器、指標函數】

目錄標題機器學習基礎知識概覽激活函數 (Activation Functions)損失函數 (Loss Functions / Cost Functions)優化器 (Optimizers)正則化 (Regularization)調度器 (Schedulers / Learning Rate Schedulers)指標函數 (Metric Functions)其他重要概念訓練流程機器學習基礎知識概覽…

【達夢數據庫|JPA】后端數據庫國產化遷移記錄

項目背景 經典的springbootjpa&#xff0c;java1.8數據庫MySQL需要遷移到國產化數據庫達夢上 開發環境安裝 最簡單的方式&#xff1a; 官方網站下載安裝時選擇“典型安裝”即可 Linux安裝 國產化一律上docer不要猶豫 下載三方提供的docker鏡像按頁面文檔啟動即可同上下載官…

ubuntu22默認安裝firefox使用snap安裝還老打不開解決辦法

終極解決方案&#xff08;100% 避免 Snap 版 Firefox&#xff09; 步驟 1&#xff1a;徹底移除 Snap 版 Firefox bash sudo snap remove --purge firefox 步驟 2&#xff1a;添加 Mozilla 官方 PPA&#xff08;提供 .deb 版 Firefox&#xff09; bash sudo add-apt-repository …

MyBatis02-mybatis-config.xml配置文件講解

mybatis-config.xml 是 MyBatis 的核心配置文件&#xff0c;用于配置整個 MyBatis 框架的全局行為&#xff0c;比如環境&#xff08;數據源&#xff09;、事務、類型別名、插件、Mapper 映射等。示例&#xff1a;<?xml version"1.0" encoding"UTF-8" ?…

合上電腦不關機

在Debian 系統上&#xff0c;如何實現合上電腦不關機的效果&#xff1f; 可以修改配置文件&#xff1a; sudo vim /etc/systemd/logind.conf1.找到 HandleLidSwitch &#xff0c;將其值改為 ignore &#xff08;處理蓋子開關為忽略&#xff09; 2.將 LidSwitchIgnoreInhibited …

服務器深夜告警?可能是攻擊前兆!

凌晨三點&#xff0c;刺耳的告警鈴聲把你從夢中驚醒&#xff1a;服務器CPU 100%&#xff0c;內存耗盡&#xff01;你手忙腳亂地登錄服務器&#xff0c;發現某個進程瘋狂占用資源。是程序Bug&#xff1f;還是業務突增&#xff1f;排查半天&#xff0c;最后在角落的日志里發現蛛絲…