给定一个整数数组 (下标由 0 到 n-1,其中 n 表示数组的规模,数值范围由 0 到 10000),以及一个 查询列表。对于每一个查询,将会给你一个整数,请你返回该数组中小于给定整数的元素的数量。
注意事项:
在做此题前,最好先完成 线段树的构造 and 线段树查询 II 这两道题目。
样例:
对于数组 [1,2,7,8,5] ,查询 [1,8,5],返回 [0,4,2]
挑战
可否用一下三种方法完成以上题目。
1. 仅用循环方法
2. 分类搜索 和 二进制搜索
3. 构建 线段树 和 搜索
loop?
#ifndef C248_H
#define C248_H
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
class Solution {
public:
/*
* @param A: An integer array
* @param queries: The query list
* @return: The number of element in the array that are smaller that the given integer
*/
vector<int> countOfSmallerNumber(vector<int> &A, vector<int> &queries) {
// write your code here
vector<int> v;
if (queries.empty())
return v;
if (A.empty())
{
for (int i = 0; i < queries.size(); ++i)
v.push_back(0);
return v;
}
map<int, int> m;
sort(A.begin(), A.end());
for (int j = 0; j < A.size(); ++j)
m[A[j]] = j;
for (int k = 0; k < queries.size(); ++k)
{
if (queries[k] <= A[0])
{
v.push_back(0);
continue;
}
for (int i = A.size() - 1; i >= 0; --i)
{
if (queries[k]>A[i])
{
v.push_back(m[A[i]]+1);
break;
}
}
}
return v;
}
};
#endif
二分法:
#ifndef C248_H
#define C248_H
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
/*
* @param A: An integer array
* @param queries: The query list
* @return: The number of element in the array that are smaller that the given integer
*/
vector<int> countOfSmallerNumber(vector<int> &A, vector<int> &queries) {
// write your code here
vector<int> v;
sort(A.begin(), A.end());
for (auto c : queries)
{
int num = lower_bound(A.begin(), A.end(), c) - A.begin();
v.push_back(num);
}
return v;
}
};
#endif
线段树
由于数组范围0~10000,不妨构建0~10000的搜索树,使用函数build(0,10000);
对于A中出现的数字index,对搜索树进行修改,modify(root,index),start==index且
end==index的节点count值+1;最后,对于queries中的数value,query(root,0,value-1 ),
即求得A中比value小的数出现的次数。(由于LintCode有默认的SegmentTreeNode,与本题的不符合,所以更改了类名)
#ifndef C248_H
#define C248_H
#include<iostream>
#include<vector>
using namespace std;
class SegmentNode{
public:
int start, end, count;
SegmentNode *left, *right;
SegmentNode(int start, int end,int count)
{
this->start = start, this->end = end, this->count = count;
this->left = this->right = NULL;
}
};
class Solution {
public:
/*
* @param A: An integer array
* @param queries: The query list
* @return: The number of element in the array that are smaller that the given integer
*/
vector<int> countOfSmallerNumber(vector<int> &A, vector<int> &queries) {
// write your code here
vector<int> v;
SegmentNode *root = build(0, 10000);
for (auto c : A)
modify(root, c);
for (auto t : queries)
v.push_back(query(root, 0, t - 1));
return v;
}
SegmentNode *build(int start, int end)
{
if (start > end)
return NULL;
SegmentNode *node = new SegmentNode(start, end, 0);
if (start == end)
return node;
node->left = build(start, (start + end) / 2);
node->right = build((start + end) / 2 + 1, end);
return node;
}
void modify(SegmentNode *root, int index)
{
if (!root)
return;
if (root->start == root->end)
{
if (root->start == index)
root->count++;
return;
}
modify(root->left, index);
modify(root->right, index);
root->count = root->left->count + root->right->count;
}
int query(SegmentNode * root, int start, int end) {
// write your code here
if (start > end || root == NULL||start<root->start||end>root->end)
return 0;
SegmentNode *node = root;
if (start >= node->start&&end <= node->end&&node->count == 0)
return 0;
if (start == node->start&&end == node->end)
return node->count;
if (end <= node->left->end)
{
return query(node->left, start, end);
}
else if (start >= node->right->start)
{
return query(node->right, start, end);
}
else
{
int l = query(node->left, start, node->left->end);
int r = query(node->right, node->right->start, end);
return l + r;
}
}
};
#endif