算法題打卡力扣第34題:在排序數組中查找元素的第一個和最后一個位置(mid)

題目描述

在這里插入圖片描述
提示:

0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一個非遞減數組
-109 <= target <= 109

解題思路一

暴力解
頭到尾遍歷整個數組。
用一個變量 first 記錄第一次遇到 target 的索引。
繼續遍歷,用另一個變量 last 不斷更新最后一次遇到 target 的索引。
如果遍歷結束后 first 仍然是初始值(例如 -1),說明目標值不存在,返回 [-1, -1]。
否則,返回 [first, last]。
代碼實現:

/*** Note: The returned array must be malloced, assume caller calls free().*/
int* searchRange(int* nums, int numsSize, int target, int* returnSize) {int* result = (int*)malloc(sizeof(int) * 2);*returnSize = 2;int i = 0;int first = -1, last = -1;for (i = 0; i < numsSize; i++) {if (nums[i] == target) {first = i;break;}}if (first == -1) {result[0] = -1;result[1] = -1;return result;}for (i = first; i < numsSize; i++) {if (nums[i] == target) {last = i;}}result[0] = first;result[1] = last;return result;
}

執行結果:
在這里插入圖片描述

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int first = -1,last=-1;for(int i=0;i<nums.size();++i){if(nums[i]==target){first = i;break;}}if(first==-1){return{-1,-1};}for(int i=nums.size()-1;i>=first;--i){if(nums[i]==target){last = i;break;}}return {first,last};}
};

在這里插入圖片描述

復雜度分析:
時間復雜度:O(n)
空間復雜度:O(1)

解法二:二分查找

兩次二分查找是最優解

一次查找用于定位第一個等于 target 的位置(左邊界)。
另一次查找用于定位最后一個等于 target 的位置(右邊界)。

.1 查找左邊界(First Position)
我們需要修改二分查找的邏輯,使得當 nums[mid] == target 時,我們不立即返回,而是嘗試在左半部分繼續尋找,看看有沒有更靠前的 target。
具體步驟:
初始化 left = 0, right = n-1, first_pos = -1。
初始化 left = 0,right = n-1,first_pos = -1。

進入 while (left <= right) 循環。
輸入 while(left <= right) 循環。

計算 mid = left + (right - left) / 2。
計算 mid = left +(right - left)/ 2。

關鍵邏輯:
如果 nums[mid] > target,說明目標值在左側,right = mid - 1。
如果 nums[mid] < target,說明目標值在右側,left = mid + 1。
如果 nums[mid] == target,我們找到了一個 target。但它不一定是第一個。所以我們先將這個位置記錄下來 first_pos = mid,然后繼續在左半部分搜索,即 right = mid - 1,試圖找到一個更小的索引。
循環結束后,first_pos 中存儲的就是第一個目標值的位置。

2.2 查找右邊界(Last Position)
邏輯與查找左邊界非常相似,只是當找到 target 時,我們嘗試在右半部分繼續尋找。
具體步驟:
初始化 left = 0, right = n-1, last_pos = -1。
初始化 left = 0,right = n-1,last_pos = -1。

進入 while (left <= right) 循環。
輸入 while(left <= right) 循環。

計算 mid = left + (right - left) / 2。
計算 mid = left +(right - left)/ 2。

關鍵邏輯:
如果 nums[mid] > target,說明目標值在左側,right = mid - 1。
如果 nums[mid] < target,說明目標值在右側,left = mid + 1。
如果 nums[mid] == target,我們找到了一個 target。但它不一定是最后一個。所以我們先將這個位置記錄下來 last_pos = mid,然后繼續在右半部分搜索,即 left = mid + 1,試圖找到一個更大的索引。
循環結束后,last_pos 中存儲的就是最后一個目標值的位置。
最終:先執行查找左邊界的二分,如果沒找到(返回-1),直接返回 [-1, -1]。如果找到了,再執行查找右邊界的二分,最后將兩個結果組合成 [first_pos, last_pos] 返回。

代碼實現:

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int first_pos= -1, last_pos = -1;int left=0,right=nums.size()-1;while(left<=right){int mid = left+(right-left)/2;if(nums[mid]>target)right = mid-1;else if(nums[mid]<target)left=mid+1;else{first_pos=mid;right = mid-1;}}if(first_pos==-1)return {-1,-1};left = 0; right = nums.size() - 1;while(left<=right){int mid = left+(right-left)/2;if(nums[mid]>target)right = mid-1;else if(nums[mid]<target)left=mid+1;else{last_pos=mid;left = mid+1;}}return {first_pos,last_pos};}
};

執行結果
在這里插入圖片描述
復雜度分析:
時間復雜度:O(logn)
空間復雜度:O(1)
優化在第二次while循環時,只在 [first_pos, n-1] 范圍內搜索而不是從【0,n-1】
在這里插入圖片描述

思路三

巧用二分查找尋找邊界(思路二的變體)

這個思路更加巧妙,它將問題轉化為**“尋找第一個大于等于 target 的位置”** 和 “尋找第一個大于 target 的位置”。

尋找左邊界:
我們執行一次二分查找,目的是找到第一個大于或等于 target 的元素的索引。這個索引就是我們要的左邊界 left_bound。
這個查找過程也被稱為 lower_bound。
尋找右邊界:
我們再執行一次二分查找,目的是找到第一個大于 target 的元素的索引。
那么,這個索引減一,就是我們要的右邊界 right_bound。
這個查找過程也被稱為 upper_bound。
驗證結果:
在找到 left_bound 后,需要檢查一下 nums[left_bound] 是否真的等于 target。如果不是,或者 left_bound 越界了,說明 target 根本不存在,直接返回 [-1, -1]

#include <iostream>
#include <vector>class Solution {
public:std::vector<int> searchRange(std::vector<int>& nums, int target) {int first = -1;int last = -1;// 尋找第一個位置for (int i = 0; i < nums.size(); ++i) {if (nums[i] == target) {first = i;break; // 找到第一個就停止}}// 如果找不到,直接返回if (first == -1) {return {-1, -1};}// 尋找最后一個位置// 從后往前找會更高效for (int i = nums.size() - 1; i >= first; --i) {if (nums[i] == target) {last = i;break; // 找到第一個(從后往前看)就停止}}return {first, last};}
};

在這里插入圖片描述

復雜度分析:
時間復雜度:O(logn)
空間復雜度:O(1)
ok,see you next time~

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

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

相關文章

虛幻基礎:曲線

能幫到你的話&#xff0c;就給個贊吧 &#x1f618; 文章目錄曲線&#xff1a;數值變化的曲線動畫曲線動畫曲線get curve value只有curve所在動畫被播放才返回曲線數值沒播放時 返回0一個曲線可以在多個動畫中使用 且可以設置曲線的不同值曲線&#xff1a;數值變化的曲線 動畫…

MFC隨筆—不使用對話框資源模板創建對話框

在MFC程序中使用對話框時一般都是首先在資源模版里創建對話框資源,然后DoModal()或者Create顯示出模式對話框或者非模式對話框。然而采用該方式創建出的對話框移植性差,從一個工程移動到另一個工程比較麻煩。 在MFC中還有另一種創建對話框的方法,即利用DLGTEMPLATE、DLGITEM…

第八十六章:實戰篇:文本生成腳本 → TTS + 鏡頭 → 視頻整合——讓你的文字“動聽”又“好看”!

AI導演鏈路前言&#xff1a;AI的“智能制片人”——文本 → 視頻&#xff0c;你的想法“一鍵出片”&#xff01;第一章&#xff1a;痛點直擊——傳統視頻制作&#xff0c;累到“吐血”&#xff01;第二章&#xff1a;探秘“智能制片廠”&#xff1a;流水線上的四大核心模塊&…

Linux內核源碼詳解--缺頁異常(Page Fault)處理的核心函數handle_pte_fault

handle_pte_fault 是 Linux 內核中處理缺頁異常&#xff08;Page Fault&#xff09;的核心函數&#xff0c;負責根據頁表項&#xff08;PTE&#xff09;的狀態和訪問權限&#xff0c;分發到不同的子處理邏輯&#xff08;如匿名頁映射、文件頁映射、寫時復制、NUMA 遷移等&#…

基于混合注意力網絡和深度信念網絡的魯棒視頻水印技術基礎理論深度解析

1. 引言隨著數字媒體技術的迅猛發展和互聯網的普及&#xff0c;視頻內容的創作、傳播和分享變得前所未有的便捷。然而&#xff0c;這種便利性也帶來了嚴重的版權保護挑戰。數字視頻的易復制性使得盜版和非法傳播成為困擾內容創作者和版權所有者的重大問題。傳統的加密技術雖然能…

linux 之virtio 的驅動框架

1、基本知識 上一篇文章介紹了 virtio 的核心數據的實現和邏輯&#xff1a;linux 之 virtio 子系統核心的數據結構-CSDN博客 virtio 是對半虛擬化 hypervisor 中的一組通用模擬設備的抽象。它允許 hypervisor 導出一組通用的模擬設備&#xff0c;并通過一個通用的應用編程接口…

項目1總結其三(圖片上傳功能)

1、UploadService public interface UploadService {//上傳圖片String uploadImage(MultipartFile file, String type); }upload.location D:/upload Value("${upload.location}")private String uploadLocation;//文件上傳路徑Overridepublic String uploadImage(M…

Linux應用層開發--線程池介紹

Glib 線程池 1. 線程池簡介 線程池是一種管理和重用多個線程的設計模式&#xff1a; 避免頻繁創建/銷毀線程的開銷。提高性能與資源利用率。任務提交后&#xff0c;由線程池內的線程自動執行&#xff0c;任務執行完線程不會退出&#xff0c;而是繼續等待下一個任務。 2. Gli…

【Python】Python 多進程與多線程:從原理到實踐

Python 多進程與多線程&#xff1a;從原理到實踐 文章目錄Python 多進程與多線程&#xff1a;從原理到實踐前言一、并發編程基礎&#xff1a;進程與線程1.1 進程&#xff08;Process&#xff09;1.2 線程&#xff08;Thread&#xff09;1.3 進程與線程的關系二、Python 中的 &q…

electron-vite_18Less和Sass共用樣式指定

項目中可以封裝less公用樣式和方法&#xff0c;比如自動以滾動條樣式、單行省略號、多行省略號、display:none等&#xff1b;關于additionalData的配置生效,請在main.js中引入一個別的樣式或vue組件中使用“<style lang“scss”><style>”找到electron.vite.config…

Python面試題及詳細答案150道(71-80) -- 文件操作篇

《前后端面試題》專欄集合了前后端各個知識模塊的面試題&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

python新工具-uv包管理工具

uv 是一個由 Astral (Ruff 的創建者) 開發的極速 Python 包和項目管理器&#xff0c;用 Rust 編寫。它旨在作為傳統 Python 包管理工具&#xff08;如 pip、pip-tools、pipx、poetry、pyenv、twine 和 virtualenv 等&#xff09;的替代品&#xff0c;通過其高性能和多功能集成&…

有關spring-ai的defaultSystem與systemMessage優先級

今天在寫項目的時候想用nacos隨時修改system的prompt&#xff0c;突然發現defaultSystem的優先級比systemMessage高很多&#xff0c;廢話我就不說了&#xff0c;看圖吧。你覺得證據不夠&#xff1f;那這樣呢&#xff1f;

#運維 | 前端 # Linux http.server 實踐:隱藏長文件名,簡短路徑 (http://IP:port/別名 ) 訪問

如何運行頁面為 http://ip:port/名稱 1. 準備文件目錄 假設文件原始位置&#xff1a; /home/ubuntu/projects/yinran/ckd.html將它移動到子目錄并改名為 index.html&#xff1a; mkdir -p /home/ubuntu/projects/yinran/ckd mv /home/ubuntu/projects/yinran/ckd.html \/home/u…

任務管理器不刷新

記錄一個小問題&#xff1a; 進入任務管理器之后發現頁面不會刷新&#xff0c;性能界面也是一致。解決辦法&#xff1a;查看–>更新速度–>正常

2025-08-21 Python進階9——__main__與lambda

文章目錄1 \_\_main\_\_1.1 name 變量1.1.1 當模塊作為主程序直接運行時1.1.2 當模塊被其他模塊導入時1.2 \_\_main\_\_ 的含義1.3 if \_\_name\_\_ \_\_main\_\_1.5 小結2 lambda表達式2.1 基本概念2.2 lambda 函數語法2.3 使用示例2.4 與高階函數結合使用2.4.1 與 map () 結…

Java:將視頻上傳到騰訊云并通過騰訊云點播播放

功能需求:傳入一個videoFile也就是視頻字節流,返回騰訊云點播的視頻保存url需要在騰訊云中尋找的配置信息:導入的依賴:<!--騰訊云點播--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId&…

Unity3D物理游戲網絡同步指南

前言 Unity3D 物理游戲的網絡同步是一個復雜但非常核心的話題。要實現一個流暢、公平且可擴展的多人物理游戲&#xff0c;需要深入的理解和精心的設計。 下面我將為你全面解析 Unity3D 物理游戲的網絡同步&#xff0c;包括核心概念、主流方案、實現細節以及最佳實踐。 對惹&…

Amazon Redshift 訪問配置完整指南

概述 Amazon Redshift 是 AWS 提供的云端數據倉庫服務,支持多種訪問方式。本文將詳細介紹如何配置 IAM 權限、使用 AWS 控制臺 Query Editor v2,以及通過 SQL Workbench/J 等第三方工具連接 Redshift 集群。 目錄 環境準備 IAM 權限配置 Redshift 用戶管理 AWS 控制臺訪問 …

electron-vite_19配置環境變量

前端配罟環境變量主要通過項目根目錄下的.env系列文件實現&#xff0c;不同框架(如Vue、React)或構建工具(如Vite、Webpack)的具體操作略有差異&#xff0c;但核心邏輯均為通過環境變量文件區分開發、測試、生產等環境。方案1: 直接在根目錄新建.env文件 1.在根目錄新建 .env.d…