文章目录

  • ​​一、使用递归实现二分法​​
  • ​​1、递归三要素分析​​
  • ​​2、代码示例​​
  • ​​二、if else 编码优化​​






一、使用递归实现二分法



​https://leetcode.cn/problems/binary-search/​

典型的二分查找题目 : 从一个 有序数组 中查找某个 目标值 , 返回 该目标元素在数组中的索引值 , 如果 数组中没有该 目标值 , 则返回 -1 ;

如 : 从 [1 , 2 , 4 , 5 , 6] 中查找 目标值 2 , 返回 2 对应的数组元素索引 为 1 ; 如果从上述数组中查找 3 , 数组中没有该元素 , 则返回 -1 ;



使用 递归 实现 二分法 , 目的是 不断 缩小二分区间 , 每次 进行递归的操作 是 取一个 中点 , 进行比较 , 确定向左收缩还是向右收缩 ;

二分法 的 时间复杂度是 【算法】递归算法 ② ( 使用递归实现二分法 | if else 编码优化 )_递归三要素 , 递归的深度也是 【算法】递归算法 ② ( 使用递归实现二分法 | if else 编码优化 )_递归_02 , 基本不会出现栈溢出 ;

如果递归深度是 【算法】递归算法 ② ( 使用递归实现二分法 | if else 编码优化 )_leetcode_03



1、递归三要素分析



分析 使用递归实现二分法 的 递归三要素 :

  • 递归定义 : 分析函数的 参数 , 返回值 , 以及代表的含义 ;
  • 参数分析 : 二分法需要接收四个参数 ,
  • 数组集合 ,
  • 查找元素的区间范围 , 起始索引 和 终止索引
  • 进行对比的目标值
  • 返回值分析 : 返回值就是 获取的 目标值 在数组中的索引 ;
  • 递归拆解 : 分析每次 递归需要执行的操作 , 就是递归函数的具体内容 ;
  • 缩小查找规模 : 二分法的核心操作就是 不断缩小 查找元素的区间范围 , 判断 区间中心元素 与 目标值的 大小关系
    - 如果 中心元素 = 目标值 , 直接返回该索引值 ;
    - 如果 中心元素 < 目标值 , 则需要去 该查找区间的 右侧继续查找 ;
    - 如果 中心元素 > 目标值 , 则需要去 该查找区间的 左侧继续查找 ;
  • 递归出口 : 每个递归都需要一个 停止条件 , 递归不断循环会造成栈内存溢出 ;
  • 没有找到 : 如果查找的区间范围出现 起始位置 > 结束位置
  • 成功找到 : 如果查找过程中出现 中心元素 = 目标值


2、代码示例



class Solution {
public int search(int[] nums, int target) {
return binarySearch(nums, 0, nums.length - 1, target);
}

// 1. 递归定义 : 分析函数的 参数 , 返回值 , 以及代表的含义
// 二分法需要接收四个参数 :
// 数组集合
// 查找元素的区间范围 , 起始索引 和 终止索引 , 这是 2 个参数
// 进行对比的目标值
// 返回值 : 进行对比的目标值
private int binarySearch(int[] nums, int start, int end, int target) {
// 3. 递归出口 :
// 没有找到 : 如果查找的区间范围出现 起始位置 > 结束位置 ,
// 说明没有找到该元素 , 直接返回 -1 ;
if (start > end) {
return -1;
}
// 成功找到 : 如果查找过程中出现 中心元素 = 目标值 , 直接返回该索引值
int mid = (start + end) / 2;
if(nums[mid] == target) {
return mid;
}

// 2. 递归拆解 : 分析每次 递归需要执行的操作 , 就是递归函数的具体内容
// 缩小查找规模 : 二分法的核心操作就是不断缩小 查找元素的区间范围 ,
// 判断区间中心元素 与 目标值的 大小关系
// 如果 中心元素 < 目标值 , 则需要去 该查找区间的 右侧继续查找
if(nums[mid] < target) {
return binarySearch(nums, mid + 1, end, target);
}
// 如果 中心元素 > 目标值 , 则需要去 该查找区间的 左侧继续查找
return binarySearch(nums, start, mid - 1, target);
}
}






二、if else 编码优化



在代码中 使用 if 进行判定时 , 推荐少用 else 语句 ;



使用了 else 关键字有以下坏处 :

  • 代码不美观 : 一旦使用了 else , 则在 else 中的 所有语句 都会缩进一行
  • 可读性差 : 在代码中 , 使用的 else 越多 , 代码的 可读性越差 ;


如果要使用 if else 语句 , 推荐将这个逻辑单独封装到一个函数中 , 在函数内部 使用 if return 来替代 if else ;

下面的代码的判定方式 判定 nums[mid] 和 target 的大小 , 有三种情况 :

  • 等于
  • 小于
  • 大于

可以 使用 if else 语句 进行编码 , 但是此处 使用了 if return 的形式

if(nums[mid] == target) {
return mid;
}
if(nums[mid] < target) {
return binarySearch(nums, mid + 1, end, target);
}
return binarySearch(nums, start, mid - 1, target);