leetcode刷题技巧之二分查找模板

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43152052/article/details/100155284

二分查找的前提:
查找的序列需要是有序的,若是无序的,则需要先给序列排序,然后再进行二分查找。

二分查找成功的三个步骤:

  • 1)预处理:如果序列未排序,则先进行排序
  • 2)二分查找:使用循环或递归将中间值元素与目标元素进行比较,将区间划分为两个子区间,然后再符合条件的其中一个子区间内进行寻找,直至循环或递归结束。
  • 3)后处理:在循环或递归完成后,需要对剩余区间的元素中确定符合条件的元素

模板1:

int binarySearch(vector<int>& nums, int target)
{
  if(nums.size() == 0) return -1;
  int left = 0, right = nums.size() - 1;
  while(left <= right)
  {
  // Prevent (left + right) overflow
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid - 1; }
  }
  // End Condition: left > right即left=right+1
  return -1;
}

模板1的关键属性:

  • 1)模板1是二分查找最基本和最基础的形式
  • 2)查找元素可以不与元素两侧进行比较下确定,即向左查找为right=mid-1,向右查找为left=mid+1
  • 3)不需要进行后处理,因为在循环结束后,区间的元素数量为0

区别语法:

  • 1)二分区间为[0,size-1]
  • 2)向左查找right=mid-1;向右查找left=mid+1
  • 3)循环结束条件是:left>right即left=right+1

模板2:

int binarySearch(vector<int>& nums, int target)
{
  if(nums.size() == 0)
    return -1;
  int left = 0, right = nums.size();
  while(left < right)
  {
    // Prevent (left + right) overflow
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid; }
  }
  // Post-processing:
  // End Condition: left == right
  if(left != nums.size() && nums[left] == target) return left;
  return -1;
}      

模板2的关键属性:

  • 1)模板2是二分查找的的高级方法,它用于查找需要访问数组中当前索引其直接右邻居索引的元素或条件(mid为中间元素,我们不仅需要判断mid指向的元素是否满足条件,我们还需要判断mid的右邻居元素是否满足条件:若mid指向的元素和右邻居元素mid+1满足条件时,我们只需要判断mid左边的元素是否满足条件就好了,所以下一次查找子区间的右边界right就是mid所代表的元素了,即right=mid;若mid指向的元素不满足条件时,那我们还需要判断右邻居元素mid+1是否满足条件,则我们向右查找left=mid+1即left为mid的右邻居元素)
  • 2)查找的区间范围至少两个元素
  • 3)需要进行后处理,循环结束的条件是left=right即左右边界指向同一个元素,我们需要判断这个元素是否符合题目规定

区别语法:

  • 1)二分区间为[0,size)
  • 2)向左查找:right=mid,向右查找:left=mid+1
  • 3)循环结束的条件是:left=right

模板3:

int binarySearch(vector<int>& nums, int target){
    if (nums.size() == 0)
        return -1;
    int left = 0, right = nums.size() - 1;
    while (left + 1 < right)
    {
    // Prevent (left + right) overflow
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {return mid;}
        else if (nums[mid] < target) {left = mid;} 
        else {right = mid;}
    }
    // Post-processing:
    // End Condition: left + 1 == right
    if(nums[left] == target) return left;
    if(nums[right] == target) return right;
    return -1;
}
              

模板3的关键属性:

  • 1)模板3是二分查找的另一种独特方式,它用于查找需要访问当前索引及其在数组中的直接左右邻居索引的元素或条件(mid为中间元素,我们不仅需要判断mid是否满足条件而且还需要判断mid的左右邻居是否满足条件:若mid满足条件,我们还需要判断mid的左邻居元素是否满足条件,即right=mid;若mid不满足条件,则我们还需要判断mid的右邻居元素是否满足条件,即left=mid)
  • 2)查找的区间中至少含有三个元素
  • 3)需要进行后处理,循环结束的条件是left+1=right,我们需要判断left和right指向的元素是否为目标值

区分语法:

  • 1)二分区间为[0,size-1]
  • 2)向左查找:right=mid,向右查找:left=mid
  • 3)循环结束的条件是:left+1=right

二分法的练习题:

题目 题解 难度
4. 寻找两个有序数组的中位数 C++ hard
33. 搜索旋转排序数组 C++ medium
34. 在排序数组中查找元素的第一个和最后一个位置 C++ medium
50. Pow(x, n) C++ mdium
69. x 的平方根 C++ easy
153. 寻找旋转排序数组中的最小值 C++ medium
154. 寻找旋转排序数组中的最小值 II C++ hard
162. 寻找峰值 C++ medium
278. 第一个错误的版本 C++ easy
287. 寻找重复数 C++ medium
209. 长度最小的子数组 C++ medium
349. 两个数组的交集 C++ easy
350. 两个数组的交集 II C++ easy
367. 有效的完全平方数 C++ easy
374. 猜数字大小 C++ easy
410. 分割数组的最大值 C++ hard
454. 四数相加 II C++ medium
658. 找到 K 个最接近的元素 C++ medium
704. 二分查找 C++ easy
719. 找出第 k 小的距离对 C++ hard

猜你喜欢

转载自blog.csdn.net/qq_43152052/article/details/100155284