【算法通关村 Day9】二分查找与二叉树的中序遍历
二分查找与二叉树的中序遍历青铜挑战
二分查找
二分查找(Binary Search)是一种在已排序的数组中查找某个特定元素的算法。通过每次将查找范围缩小一半来提高查找效率,时间复杂度为 O(log n)。
而传统的顺序查找,必须要遍历查找范围:
public int search(int[] array, int key){
for (int i = 0; i < array.length; i++) {
if(array[i] == key){
return i;
}
}
return -1;
}
- 二分查找每次将查找的范围一分为二,比较目标值与当前中间值的大小,从而确定是在左半部分还是右半部分继续查找。
- 如果找到目标值,返回其索引。如果找不到,返回 -1。
public class BinarySearch {
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;// 防止溢出
if (arr[mid] == target) {
return mid;
} else if (arr[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int target = 7;
int result = binarySearch(arr, target);
if (result != -1) {
System.out.println("目标值 " + target + " 在索引 " + result + " 位置");
} else {
System.out.println("目标值 " + target + " 不存在于数组中");
}
}
}
二分查找与二叉树的中序遍历白银挑战
二分查找在搜索树中的应用
二叉搜索树中的搜索
leetcode700
给定二叉搜索树(BST)的根节点 root
和一个整数值 val
。
你需要在 BST 中找到节点值等于 val
的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null
。
可以通过二叉搜索树的性质来高效地查找节点。二叉搜索树有一个特点:对于每个节点,左子树的值都小于该节点的值,右子树的值都大于该节点的值。因此,我们可以根据给定的值与当前节点值的比较来决定接下来是向左子树还是向右子树查找。
- 如果当前节点值等于给定的值
val
,则返回该节点。 - 如果当前节点值大于
val
,则在左子树中查找。 - 如果当前节点值小于
val
,则在右子树中查找。 - 如果遍历到
null
,则返回null
,表示没有找到该节点。
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class SearchBST {
public TreeNode searchBST(TreeNode root, int val){
if (root == null || root.val == val) {
return root;
}
if (val < root.val) {
return searchBST(root.left, val);
} else {
return searchBST(root.right, val);
}
}
}
验证二叉树是否是二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
解法:
判断二叉树是否是有效的二叉搜索树(BST)通常可以通过递归来实现。要保证每个节点满足 BST 的特性,我们需要确保每个节点的值都在其合法的范围内。具体步骤如下:
- 递归的基本思想:对于当前节点,要求其左子树所有节点的值小于当前节点的值,右子树所有节点的值大于当前节点的值。同时,左子树和右子树必须分别是合法的二叉搜索树。
- 利用上下界:每个节点的值都有一个合法范围,可以用一个递归函数来表示,每次递归时,传递给子树的合法值范围。
- 递归出口:如果当前节点为空(即没有子树),那么它一定是合法的二叉搜索树,返回
true
。
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class IsValidBST {
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private boolean isValidBST(TreeNode node, long min, long max) {
if (node == null) {
return true;
}
if (node.val <= min || node.val >= max) {
return false;
}
return isValidBST(node.left, min, node.val) && isValidBST(node.right, node.val, max);
}
}
解释:
- isValidBST 方法:调用
isValidBST
方法时,传入的是root
节点以及初始的范围Long.MIN_VALUE
和Long.MAX_VALUE
,代表所有节点的值必须在这个范围内。 - isValidBST (TreeNode node, long min, long max):这是递归检查每个节点是否符合 BST 的条件。对于每个节点,检查它的值是否在
min
和max
之间。如果不在这个范围内,返回false
。然后递归地检查它的左子树和右子树,更新合法的范围:- 对于左子树,新的合法范围是
min
到当前节点的值(node.val
)。 - 对于右子树,新的合法范围是
node.val
到max
。
- 对于左子树,新的合法范围是
时间复杂度&空间复杂度
- 时间复杂度为 O(n),其中 n 是二叉树中的节点数。每个节点都只访问一次。
- 空间复杂度:最坏情况下,递归的深度是 O(h),其中 h 是树的高度。如果树是完全平衡的,h = log n;如果树是链式结构的,h = n。所以空间复杂度为 O(h)。