- Search Range in Binary Search Tree
中文English
Given a binary search tree and a range [k1, k2], return node values within a given range in ascending order.
Example
Example 1:
Input:{5},6,10
Output:[]
5
it will be serialized {5}
No number between 6 and 10
Example 2:
Input:{20,8,22,4,12},10,22
Output:[12,20,22]
Explanation:
20
/
8 22
/
4 12
it will be serialized {20,8,22,4,12}
[12,20,22] between 10 and 22
解法1:
先把inOrder Traversal的结果求出来,再比较。
注意:
- lower_bound()和upper_bound()返回结果都是iterator,必须减去inOrderList.begin();
- lower_bound()和upper_bound()都是基于排序数组,因为要用二分查找。
- lower_bound(l,r,m)在l和r中的前闭后开区间进行二分查找,返回大于或等于m的第一个元素位置 (或者说返回m的第一个可插入位置)。如果所有元素都小于m, 则返回r的位置(注意r是最后一个元素的后一个位置,因为是前闭后开区间)。
Example: vector nums = {4,10,11,30,69,70,96,100}。设要插入数字3,9,111, pos为要插入的位置的下标
pos = lower_bound( nums.begin(), nums.end(), 3) - nums.begin(),pos = 0
pos = lower_bound( nums.begin(), nums.end(), 9) - nums.begin(), pos = 1
pos = lower_bound( nums.begin(), nums.end(), 111) - nums.begin(), pos = 8 (最后一个元素的下一个元素)。
返回查找元素的第一个可插入位置,也就是“元素值>=查找值”的第一个元素的位置
4) upper_bound(l,r,m)在l和r中的前闭后开区间进行二分查找,返回最后一个m在数组中的下标+1。
特殊情况:
a.如果m在区间中没有出现过,那么返回第一个比m大的数的下标。
b.如果m比所有区间内的数都大,那么返回r。这个时候会越界,小心。
c.如果区间内有多个相同的m,返回最后一个m的下标+1。
5) lower_bound的意义是对于给定的已经排好序的a,key最早能插入到那个位置
upper_bound的意义是对于给定的已经排好序的a,key最晚能插入到那个位置
举例:
int a[]={0,1,2,2,3};
lower_bound(a,a+5,2)-a); //=2
upper_bound(a,a+5,2)-a); //=4
结果:2 4
0 1 | 2 2 3 所以2最早插入到2号位置
0 1 2 2 | 3 所以2最晚插入到4号位置0 1 | 2 2 3 所以2最早插入到4号位置
6) lower_bound()和upper_bound()还可以加入cmp函数。
代码如下:
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: param root: The root of the binary search tree
* @param k1: An integer
* @param k2: An integer
* @return: return: Return all keys that k1<=key<=k2 in ascending order
*/
vector<int> searchRange(TreeNode * root, int k1, int k2) {
if (!root || k1 > k2) return vector<int>();
inOrderTraversal(root);
int n = inOrderList.size();
vector<int> result;
int low = lower_bound(inOrderList.begin(), inOrderList.end(), k1) - inOrderList.begin();
if (low >= n) return vector<int>();
int up = upper_bound(inOrderList.begin(), inOrderList.end(), k2) - inOrderList.begin();
if (up > n) return vector<int>();
for (int i = low; i < up; ++i) {
result.push_back(inOrderList[i]);
}
return result;
}
private:
void inOrderTraversal(TreeNode * root) {
if (!root) return;
inOrderTraversal(root->left);
inOrderList.push_back(root->val);
inOrderTraversal(root->right);
}
vector<int> inOrderList;
};
解法2:直接在inOrderTraversal里面判断。一步到位。
代码如下:
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: param root: The root of the binary search tree
* @param k1: An integer
* @param k2: An integer
* @return: return: Return all keys that k1<=key<=k2 in ascending order
*/
vector<int> searchRange(TreeNode * root, int k1, int k2) {
if (!root || k1 > k2) return vector<int>();
inOrderTraversal(root, k1, k2);
return result;
}
private:
void inOrderTraversal(TreeNode * root, int k1, int k2) {
if (!root) return;
inOrderTraversal(root->left, k1, k2);
if (root->val >= k1 && root->val <= k2) {
result.push_back(root->val);
}
inOrderTraversal(root->right, k1, k2);
}
vector<int> result;
};
解法3:先找出最开始处于k1,k2中的那个root,然后in-order迭代,如果发现某个节点>k2,那么就退出。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: param root: The root of the binary search tree
* @param k1: An integer
* @param k2: An integer
* @return: return: Return all keys that k1<=key<=k2 in ascending order
*/
vector<int> searchRange(TreeNode *root, int k1, int k2) {
vector<int> res;
stack<TreeNode *> stk;
while (root) {
if (root->val >= k1) break;
if (root->val < k1) {
root = root->right;
if (root && root->val >= k1) {
break;
}
}
}
while (root || !stk.empty()) {
while (root) {
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
if (root->val >= k1 && root->val <= k2) {
res.push_back(root->val);
} else if (root->val > k2) {
break;
}
root = root->right;
}
return res;
}
};