基于二分查找的拓展问题
山脉数组的峰顶索引
此时 mid
的值三种情况
- mid 对应在山峰的左侧 对应的条件是 arr[mid] > arr[mid - 1] && arr[mid] < arr[mid + 1]
- mid 对应在山峰的右侧 arr[mid] < arr[mid - 1] && arr[mid] > arr[mid + 1]
- mid 就是在山峰位置上,就是在最大位置处,大于左侧和右侧的值,arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]
class Solution {
public int peakIndexInMountainArray(int[] arr) {
if (arr.length == 3) {
return 1;
}
int left = 1, right = arr.length - 2;
while (left < right) {
int mid = left + ((right - left) >> 1);
if (arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]) {
return mid;
}
if (arr[mid] > arr[mid - 1] && arr[mid] < arr[mid + 1]) {
// 上升区间
left = mid + 1;
}
if (arr[mid] < arr[mid - 1] && arr[mid] > arr[mid + 1]) {
// 下降区间
right = mid - 1;
}
}
return left;
}
}
旋转数字的最小数字
这里仍然可以使用二分法,进行缩小范围,提高效率
图片来源 leetCode
- 当我们的初始位置中间位置在最小值的左边时,当我们的 left 到达最小值时,我们的 left 指针就在最小值的位置,而且不会改变位置直到 right 指针和 left 指针回合,退出循环。
- 当我们的初始位置的中间值在最小值在右边时,我们的的 left = pivot 那么我们的 中间值就会向左移动,直到我们的中间位置在最小值的左边时,就和上面的情况类似
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int pivot = left + ((right - left) >> 1);
// 这里存在一个前提条件就是 right 其实是最小值右边的最大值,最小值左边的最小值
if (nums[pivot] < nums[right]) {
right = pivot;
} else {
left = pivot + 1;
}
}
return nums[left];
}
}
找缺失数字
正常情况下,不缺失的话会满足 nums[X] == X
使用二分法就会出现下面几种情况
- mid 与此时的值不相等,此时 nums[X] == X 这个条件将不满足,那么就需要把 right 之指针向前移动,即 right = mid - 1
- mid 此时的位置出现确实,这种情况比较简单直接返回即可
class Solution {
public int missingNumber(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == mid) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
}
x 的平方根
public int sqrt (int x) {
int l = 1, r = x;
while(l <= r){
int mid = l + ((r - l)>>1);
if(x / mid > mid){
l = mid + 1;
} else if(x / mid < mid){
r = mid - 1;
} else if(x / mid == mid){
return mid;
}
}
return r;
}
中序与搜索树原理
中序遍历与二叉搜索树之间有紧密的关联,二叉搜索树(Binary Search Tree,BST)是一种特殊的二叉树结构,其中每个节点都满足以下特征:
- 节点的左子树(如果存在)上的所有节点的值都小于节点的值。
- 节点的右子树(如果存在)上的所有节点的值都大于节点的值。
- 左子树和右子树都是二叉搜索树。
这个定义确保了在一个二叉搜索树中,通过中序遍历可以得到一个递增的有序序列。中序遍历是一种遍历二叉树的方法,其过程是先遍历左子树,然后访问当前节点,最后遍历右子树。
对于一个二叉搜索树,使用中序遍历可以按照从小到大的顺序访问所有的节点值,这是因为中序遍历首先会访问左子树中的所有节点,然后是当前节点,最后是右子树中的所有节点。
由于中序遍历的这种性质,二叉搜索树经常被用来进行查找、插入和删除操作,因为在二叉搜索树中,查找特定值的效率相对较高。但需要注意的是,如果二叉搜索树的平衡性被破坏,它的效率可能会下降,因此在实际应用中,通常会对二叉搜索树进行平衡操作,以保持树的平衡性。
二叉搜索树中搜索特定值
使用递归
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
// 剪枝
// 边界条件是如果 root 是 null 就返回 true,如果 root 的值和 val 相等那么就直接返回 root
if (root == null || val == root.val) {
return root;
}
TreeNode node = new TreeNode();
if (root.val > val) {
node = searchBST(root.left, val);
} else {
node = searchBST(root.right, val);
}
return node;
}
}
二叉搜索树中搜索特定值
class Solution {
long pre = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
// 左中右,不要想太多
if (!isValidBST(root.left)) {
return false;
}
// 这里 root 一定不为 null
if (root.val > pre) {
pre = root.val;
} else {
return false;
}
if (!isValidBST(root.right)) {
return false;
}
return true;
}
}