使用分治的思路,算法将当前的查询范围与树中的节点表示的区间做比较,并根据不同情况继续递归查找。这种处理方式能够在树结构中快速定位到包含查询范围的节点,并进一步缩小检索范围。
如果 i>j,表示查询范围非法,直接返回空。
如果 i=j,表示查询范围只包含一个元素,直接返回该元素值。
如果 i所在区间的右边界小于等于根节点的左子树最大值,且 j所在区间的左边界大于等于根节点的右子树最小值,则整个查询范围完全包含在根节点表示的区间内,可以直接返回根节点的最小值。
如果 i所在区间的右边界大于根节点的左子树最大值,表示查询范围部分在根节点的左子树中,此时递归在左子树中进行查找。
如果 j所在区间的左边界小于根节点的右子树最小值,表示查询范围部分在根节点的右子树中,此时递归在右子树中进行查找。
#include <stdio.h>
#include <stdlib.h>
struct TreeNode {
int val;
int left_max;
int right_min;
struct TreeNode* left;
struct TreeNode* right;
};
struct TreeNode* createNode(int val, int left_max, int right_min, struct TreeNode* left, struct TreeNode* right) {
struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));
node->val = val;
node->left_max = left_max;
node->right_min = right_min;
node->left = left;
node->right = right;
return node;
}
struct TreeNode* buildTree(int arr[], int start, int end) {
if (start > end) {
return NULL;
}
if (start == end) {
return createNode(arr[start], arr[start], arr[start], NULL, NULL);
}
int mid = (start + end) / 2;
struct TreeNode* left = build(arr, start, mid);
struct TreeNode* right = build(arr, mid + 1, end);
return createNode(
min(left->val, right->val),
left->left_max,
right->right_min,
left,
right
);
}
int search(struct TreeNode* root, int i, int j) {
if (i > j) {
return -1; // 查询范围非法,返回一个合适的值表示错误
}
if (i == j) {
return root->val;
}
if (i <= root->left_max && j >= root->right_min) {
return root->val;
}
if (i > root->left_max) {
return search(root->right, i, j);
}
if (j < root->right_min) {
return search(root->left, i, j);
}
int minLeft = search(root->left, i, j);
int minRight = search(root->right, i, j);
return (minLeft < minRight) ? minLeft : minRight;
}
int main() {
int arr[] = {8, 7, 3, 9, 5, 1, 10};
int n = sizeof(arr) / sizeof(arr[0]);
struct TreeNode* root = buildTree(arr, 0, n - 1);
printf("%d\n", search(root, 1, 5)); // 输出 1
printf("%d\n", search(root, 0, 3)); // 输出 3
return 0;
}