当前位置: 首页 > article >正文

【数据结构与算法】LeetCode:二分查找

文章目录

  • 二分查找
    • 二分查找
    • 搜索插入位置 (Hot 100)
    • x 的平方根
    • 搜索二维矩阵(Hot 100)
    • 在排序数组中查找元素的第一个和最后一个位置 (Hot 100)
    • 搜索旋转排序数组 (Hot 100)
    • 寻找旋转排序数组中的最小值 (Hot 100)

二分查找

二分查找

二分查找

class Solution{
public:
    int search(vector<int>& nums, int target){
        // 设定左闭右闭的区间
        int left = 0;  
        int right = nums.size() - 1;
        while (left <= right){  // 闭区间查找,left == right依然有效,所以用<=
            int middle = left + (right-left) / 2; // 中值索引
            if (nums[middle] > target){   
                right = middle-1;   // target在左边,更新右上限
            }
            else if (nums[middle] < target){
                left = middle + 1;  // target在右边,更新左上限
            }
            else{
                return middle;    // 找到target,返回下标
            }
        }
        return -1;
    }

};

搜索插入位置 (Hot 100)

搜索插入位置

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int n = nums.size();
        int left = 0, right = n - 1, ans = n;
        while(left <= right){ 
            int mid = ((right - left) >> 1) + left;
            if(nums[mid] > target){  
                right = mid - 1;
            }else if (nums[mid] < target){
                left = mid + 1;
            }else{
                return mid;
            }
        }
        // left此时 > right
        // left指向的是第一个大于target的元素的索引
        return left;
    }
};

x 的平方根

x 的平方根

class Solution {
public:

    int mySqrt(int x) {
        int l = 0, r = x;
        while (l <= r) {
            int mid = l + (r - l) / 2;
            if ((long long) mid * mid < x) { 
                l = mid + 1;
            } else if ((long long) mid * mid > x) {
                r = mid - 1;
            }else{
                return mid;
            }
        }// l此时 > r,向下取整
        return r;
    }
};

搜索二维矩阵(Hot 100)

搜索二维矩阵

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        int left = 0, right = m * n - 1;
        while(left <= right){
            int mid = (right - left >> 2) + left;
            int x = matrix[mid / n][mid % n];
            if(x < target){
                left = mid + 1;
            }  
            else if(x > target){
                right = mid - 1;
            } 
            else{
                return true;
            }
        }
        return false;
    }
};

在排序数组中查找元素的第一个和最后一个位置 (Hot 100)

在排序数组中查找元素的第一个和最后一个位置

#include <vector>
using namespace std;

class Solution {
public:
    int binarySearch(vector<int>& nums, int target) {
        // 二分查找变形
        int left = 0, right = nums.size() - 1, ans = -1;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] == target) {
                ans = mid;
                right = mid - 1; // 找到目标值时,继续在左半部分查找
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return ans;
    }


    vector<int> searchRange(vector<int>& nums, int target) {
        // 调用binarySearch函数,查找目标值的第一个位置
        int first_pos = binarySearch(nums, target);
        if (first_pos == -1) return vector<int>{-1, -1};

        // 查找目标值的最后一个位置
        int last_pos = first_pos;
        while (last_pos < nums.size() && nums[last_pos] == target) last_pos++;
        last_pos--;


        return vector<int>{first_pos, last_pos};
    }
};

搜索旋转排序数组 (Hot 100)

搜索旋转排序数组

//定理一:只有在顺序区间内才可以通过区间两端的数值判断target是否在其中。
//定理二:判断顺序区间还是乱序区间,只需要对比 left 和 right 是否是顺序对即可,left <= right,顺序区间,否则乱序区间。
//定理三:每次二分都会至少存在一个顺序区间。


class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) return mid;
            
            if (nums[left] <= nums[mid]) {  // left 到 mid 是顺序区间
                (target >= nums[left] && target < nums[mid]) ? right = mid - 1 : left = mid + 1;
                // 如果target在顺序区间,修改区间右边界; 如果不在,修改搜索左边界
            }
            else {  // mid 到 right 是顺序区间
                (target > nums[mid] && target <= nums[right]) ? left = mid + 1 : right = mid - 1;
                  // 如果target在顺序区间,修改区间左边界; 如果不在,修改搜索右边界
            }
        }
        return -1;
    }
};


寻找旋转排序数组中的最小值 (Hot 100)

寻找旋转排序数组中的最小值

class Solution {  
public:  

    int findMin(vector<int>& nums) {  
        int low = 0;  
        int high = nums.size() - 1;  
  
        while (low < high) {  
            int pivot = low + (high - low) / 2;  

            // 如果pivot位置的值小于high位置的值,说明最小值在pivot和low之间(包括pivot)  
            if (nums[pivot] <= nums[high])  high = pivot;   
  
            // 否则,最小值在pivot和high之间(不包括pivot)  
            else  low = pivot + 1;  // (nums[pivot] > nums[high])

        }  
  
        // 当low和high相等时,说明已经找到了最小值,返回该值  
        return nums[high];  
    }  
};

if (nums[pivot] < nums[high])
在这里插入图片描述

else:


http://www.kler.cn/news/315929.html

相关文章:

  • MATLAB给一段数据加宽频噪声的方法(随机噪声+带通滤波器)
  • 【Go】Go 环境下载与安装教程(Windows系统)
  • 九、成功版--windows上安装artifactory配置postgressql
  • [Redis][环境配置]详细讲解
  • Spark-累加器源码分析
  • JS执行机制(同步和异步)
  • 深度学习入门:探索神经网络、感知器与损失函数
  • html实现TAB选项卡切换
  • LLMs之OCR:llm_aided_ocr(基于LLM辅助的OCR项目)的简介、安装和使用方法、案例应用之详细攻略
  • Python之一些列表的练习题
  • Spring Boot入门:构建你的首个Spring Boot应用
  • Mybatis-plus进阶篇(二)
  • 【JUC并发编程系列】深入理解Java并发机制:线程局部变量的奥秘与最佳实践(五、ThreadLocal原理、对象之间的引用)
  • 数据结构 ——— 常见的时间复杂度计算例题(最终篇)
  • Linux驱动开发 ——架构体系
  • 求最大公约数
  • CSS 布局三大样式简单学习
  • 【解密 Kotlin 扩展函数】命名参数和默认值(十三)
  • 【深入Java枚举类:不仅仅是常量的容器】
  • 数据结构——串的模式匹配算法(BF算法和KMP算法)
  • 设计模式-装饰者模式
  • VMware虚拟机经常性卡死,打开运行一段时间后卡死,CPU占比增至100%
  • 电脑网络怎么弄动态ip :步骤详解与优势探讨
  • Tomcat系列漏洞复现
  • AI时代最好的编程语言应该选择谁?
  • vue h5 蓝牙连接 webBluetooth API
  • MySQL 中删除重复的数据并只保留一条
  • C#实现指南:将文件夹与exe合并为一个exe
  • vscode 环境搭建
  • 神经网络修剪实战