统计比给定整数小的数的个数 -Lintcode

给定一个整数数组 (下标由 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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值