文章目录
- 一、使用递归实现二分法
- 1、递归三要素分析
- 2、代码示例
- 二、if else 编码优化
一、使用递归实现二分法
https://leetcode.cn/problems/binary-search/
典型的二分查找题目 : 从一个 有序数组 中查找某个 目标值 , 返回 该目标元素在数组中的索引值 , 如果 数组中没有该 目标值 , 则返回 -1 ;
如 : 从 [1 , 2 , 4 , 5 , 6] 中查找 目标值 2 , 返回 2 对应的数组元素索引 为 1 ; 如果从上述数组中查找 3 , 数组中没有该元素 , 则返回 -1 ;
使用 递归 实现 二分法 , 目的是 不断 缩小二分区间 , 每次 进行递归的操作 是 取一个 中点 , 进行比较 , 确定向左收缩还是向右收缩 ;
二分法 的 时间复杂度是
, 递归的深度也是
, 基本不会出现栈溢出 ;
如果递归深度是
则出现栈溢出风险较大 ;
1、递归三要素分析
分析 使用递归实现二分法 的 递归三要素 :
- 递归定义 : 分析函数的 参数 , 返回值 , 以及代表的含义 ;
- 参数分析 : 二分法需要接收四个参数 ,
- 数组集合 ,
- 查找元素的区间范围 , 起始索引 和 终止索引 , 这是 2 个参数 ,
- 进行对比的目标值
- 返回值分析 : 返回值就是 获取的 目标值 在数组中的索引 ;
- 参数分析 : 二分法需要接收四个参数 ,
- 递归拆解 : 分析每次 递归需要执行的操作 , 就是递归函数的具体内容 ;
- 缩小查找规模 : 二分法的核心操作就是 不断缩小 查找元素的区间范围 , 判断 区间中心元素 与 目标值的 大小关系 - 如果 中心元素 = 目标值 , 直接返回该索引值 ; - 如果 中心元素 < 目标值 , 则需要去 该查找区间的 右侧继续查找 ; - 如果 中心元素 > 目标值 , 则需要去 该查找区间的 左侧继续查找 ;
- 递归出口 : 每个递归都需要一个 停止条件 , 递归不断循环会造成栈内存溢出 ;
- 没有找到 : 如果查找的区间范围出现 起始位置 > 结束位置 , 说明没有找到该元素 , 直接返回 -1 ;
- 成功找到 : 如果查找过程中出现 中心元素 = 目标值 , 直接返回该索引值 ;
2、代码示例
代码语言:javascript复制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 的形式 , 代码要更加简洁 , 易读 ;
代码语言:javascript复制 if(nums[mid] == target) {
return mid;
}
if(nums[mid] < target) {
return binarySearch(nums, mid 1, end, target);
}
return binarySearch(nums, start, mid - 1, target);