大家好我是苏麟,今天看看二分查找相关的题目 .
大纲
- 二分查找拓展问题
- 山脉数组的峰顶索引
- 中序与搜索树
- 二叉搜索树中的搜索
- 验证二叉搜索树
二分查找拓展问题
山脉数组的峰顶索引
描述 :
符合下列属性的数组 arr 称为 山脉数组 :
- arr.length >= 3
- 存在 i(0 < i < arr.length - 1)使得:
arr[0] < arr[1] < … arr[i-1] < arr[i]
arr[i] > arr[i+1] > … > arr[arr.length - 1]
给你由整数组成的山脉数组 arr ,返回满足 arr[0] < arr[1] < … arr[i - 1] < arr[i] > arr[i + 1] > … > arr[arr.length - 1] 的下标 i
题目 :
LeetCode 852. 山脉数组的峰顶索引
852.山脉数组的封顶索引
分析 :
这个题其实就是前面找最小值的相关过程而已,最简单的方式是对数组进行一次遍历。
解析 :
class Solution {
public int peakIndexInMountainArray(int[] arr) {
int length = arr.length;
int n = 0;
for(int i = 0; i< length - 1;i++){
if(arr[i] > arr[i + 1]){
n = i;
break;
}
}
return n;
}
}
分析 :
使用二分来优化一下
因为此题是必为高峰数组 , 所以数组长度为 时下标1为最大值 .
解析 :
class Solution {
public int peakIndexInMountainArray(int[] arr) {
int length = arr.length;
if(length == 3){
return 1;
}
int left = 1;
int right = length - 1;
while(left < right){
int mid = (left + right) >>> 1;
if(arr[mid - 1] < arr[mid] && arr[mid] < arr[mid + 1]){
left = mid;
}
if(arr[mid - 1] > arr[mid] && arr[mid] > arr[mid + 1]){
right = mid;
}
if(arr[mid - 1] < arr[mid] && arr[mid] > arr[mid + 1]){
return mid;
}
}
return left;
}
}
中序与搜索树
在前面我们发现很多题使用前序、后序或者层次遍历都可以解决,但几乎没有中序遍历的。这是因为中序与前后序相比有不一样的特征,例如中序可以和搜索树结合在一起,但是前后序则不行。
二叉搜索树是一个很简单的概念,但是想说清楚却不太容易。简单来说就是如果一棵二叉树是搜索树,则按照中序遍历其序列正好是一个递增序列。比较规范的定义是:
- 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
- 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
- 它的左、右子树也分别为二又排序树。下面这两棵树一个中序序列是 {3.6.9,10,14,16,19},一个是{3,6,9,10},因此都是搜索树:
搜索树的题目虽然也是用递归,但是与前后序有很大区别,主要是因为搜索树是有序的,就可以根据条件决定某些递归就不必执行了,这也称为“剪枝”。
二叉搜索树中的搜索
描述 :
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
题目 :
LeetCode 700. 二叉搜索树中的搜索
700.二叉搜索树中的搜索
分析 :
本题看起来很复杂,但是实现非常简单,递归:
- 如果根节点为空 root == null 或者根节点的值等于搜索值 val == root.val,返回根节点
- 如果 val < root.val,进入根节点的左子树查找 searchBST(root.left, val)
- 如果 val > root.val,进入根节点的右子树查找 searchBST(root.right, val)
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
return searchNode(root,val);
}
public TreeNode searchNode(TreeNode root,int val){
if(root == null){
return null;
}
if(root.val == val){
return root;
}else{
if(val < root.val){
root = searchBST(root.left,val);
}else{
root =searchBST(root.right,val);
}
}
return root;
}
}
分析 :
迭代方式也很简单 , 只要值不相等就循环 , 循环到最后还没有就返回null .
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
while(root != null && root.val != val){
root = root.val > val ? root.left : root.right;
}
return root;
}
}
验证二叉搜索树
描述 :
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数
- 节点的右子树只包含 大于 当前节点的数
- 所有左子树和右子树自身必须也是二叉搜索树
题目 :
LeetCode 98. 验证二叉搜索树
验证二叉搜索树
分析 :
我们就以这个为例 :
以此代码为例讲解 :
class Solution {
public boolean isValidBST(TreeNode root) {
return is(root);
}
long pre = Long.MIN_VALUE;
public boolean is(TreeNode root){
if(root == null){
return true;
}
if(root.val <= pre){
return false;
}
pre = root.val;
return is(root.right);
}
}
第一步 :
定义变量 : long pre = Long.MIN_VALUE; 他的值为 -9223372036854775808 远远比 1 小 用来比较
第二步 :
用pre 和 root.val 比较 如果小于就返回false 否则就把root.val赋值给 pre , 最后传入节点root.right
第三步 :
以 root.right 为根节点继续比较
而下面这个代码是 递归左节点的 , 如果根节点的左节点不是二叉搜索树返回false
if(!is(root.left)){
return false;
}
解析 :
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return is(root);
}
long pre = Long.MIN_VALUE;
public boolean is(TreeNode root){
if(root == null){
return true;
}
if(!is(root.left)){
return false;
}
if(root.val <= pre){
return false;
}
pre = root.val;
return is(root.right);
}
}
这期就到这里了 , 下期见!