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

【算法笔记】二分算法原理的深度剖析

【算法笔记】二分算法原理的深度剖析

🔥个人主页大白的编程日记

🔥专栏算法笔记


文章目录

  • 【算法笔记】二分算法原理的深度剖析
    • 前言
    • 一.二分查找
      • 1.1题目
      • 1.2朴素二分
      • 1.3细节问题
      • 1.4代码实现
      • 1.5朴素模版总结
    • 二.在排序数组中查找第一个和最后一个元素的位置
      • 2.1题目
      • 2.2思路分析
      • 2.3代码实现
      • 2.4左右端点二分模板总结
    • 三.搜索插入位置
      • 3.1搜索插入位置
      • 3.2思路分析
      • 3.3代码实现
    • 四.寻找峰值
      • 4.1题目
      • 4.2思路分析
      • 4.3代码实现
    • 五.寻找旋转数组中的最小值
      • 5.1题目
      • 5.2思路分析
      • 5.3代码实现
    • 后言

前言

哈喽,各位小伙伴大家好!上期我们讲了滑动窗口的算法原理。今天我们来讲二分查找算法。话不多说,我们进入正题!向大厂冲锋!

一.二分查找

1.1题目

  • 题目:二分查找

1.2朴素二分

如果存在二段性我们就可以快速筛选掉一段不存在答案的区间

1.3细节问题

这里我们要注意循环结束条件和中点的查找。
在我们的朴素二分中中点取左端和右端都是可以的。

1.4代码实现

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;//偶数取左端,+1取右端
            if(nums[mid]<target)
            {
                left=mid+1;
            }
            else if(nums[mid]>target)
            {
                right=mid-1;
            }
            else
            {
                return mid;
            }
        }
        return -1;
    }
};

1.5朴素模版总结

这就是我们的朴素二分模版。具体括号的具体内容结合题目填充即可。?

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

2.1题目

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

2.2思路分析

  • 左端点
    在这里插入图片描述
  • 左端点细节问题
  • 右端点
  • 右端点细节问题

2.3代码实现

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        if(nums.size()==0)
        {
            return {-1,-1};
        }
        int left=0,right=nums.size()-1;
        int begin,end;
        while(left<right)//找左端点
        {
            int mid=left+(right-left)/2;//取左端点
            if(nums[mid]>=target)
            {
                right=mid;
            }
            else
            {
                left=mid+1;
            }
        }
        if(nums[left]!=target)
        {
           return {-1,-1};
        }
        begin=left;
        left=0,right=nums.size()-1;
        while(left<right)//找右端点
        {
            int mid=left+(right-left+1)/2;//取右端点
            if(nums[mid]<=target)
            {
                left=mid;
            }
            else
            {
                right=mid-1;
            }
        }
        if(nums[left]!=target)
        {
           return {-1,-1};
        }
        end=right;
        return {begin,end};
    }
};

2.4左右端点二分模板总结

  • 左端点

  • 右端点

  • 循环条件
    left<right

  • 中点操作

三.搜索插入位置

3.1搜索插入位置

  • 题目:搜索插入位置

3.2思路分析

我们只需要查找左端点即可。

3.3代码实现

  • 右端点
class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) 
    {
        int left=1,right=arr.size()-2;
        while(left<right)
        {
            int mid=left+(right-left+1)/2;
            if(arr[mid]>arr[mid-1])
            {
                left=mid;
            }
            else
            {
               right=mid-1;
            }
        }
        return left;
    }
};

  • 左端点‘
class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) 
    {
        int left=1,right=arr.size()-2;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(arr[mid]<arr[mid+1])
            {
                left=mid+1;
            }
            else
            {
               right=mid;
            }
        }
        return left;
    }
};

四.寻找峰值

4.1题目

  • 题目:寻找峰值

4.2思路分析

4.3代码实现

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

五.寻找旋转数组中的最小值

5.1题目

  • 题目:寻找旋转数组中的最小值

5.2思路分析

5.3代码实现

  • num[0]
class Solution {
public:
    int findMin(vector<int>& nums) 
    {
        int left=0,right=nums.size()-1;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]<nums[0])
            {
                right=mid;
            }
            else
            {
                left=mid+1;
            }
        }
        return nums[left]>nums[0]?nums[0]:nums[left];//特殊处理
    }
};

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

后言

这就是二分算法的深度剖析。二分算法细节还是挺多的。大家自己好好梳理一下。今天就分享到这,感谢各位的耐心垂阅!咱们下期见!拜拜~


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

相关文章:

  • 数据分析认知
  • 17 链表——21. 合并两个有序链表 ★
  • 【小技巧】mysql 判断表字段是否存在 删除字段 sql脚本
  • python爬虫 - 进阶requests模块
  • 【机器学习-无监督学习】降维与主成分分析
  • 命名管道Linux
  • Stable Diffusion绘画 | 如何做到不同动作表情,人物角色保持一致性(下篇)
  • 深度学习中的迁移学习:预训练模型微调与实践
  • 2024年liunx安装openvino非源码编译版(比源码编译简单!)
  • APP自动化搭建与应用
  • Linux 学习
  • 推荐!专业Substance 3D Painter v10.解锁版下载及安装 (3D绘画软件)
  • 最大异或对(每周一类)
  • 常用动词敬语形式大揭秘,柯桥零基础日语培训
  • 【C#生态园】提升C#图像处理与压缩效率:六款库全面比较
  • jQuery EasyUI 扩展
  • cmakelist加载Qt模块
  • 定时器定时中断定时器外部中断
  • Qt 图片显示 动态选择图片显示
  • 基于springboot的家政服务管理系统(含源码+sql+视频导入教程+文档+PPT)