剑指Offer - 九度1349 - 数字在排序数组中出现的次数
- 剑指Offer - 九度1349 - 数字在排序数组中出现的次数
2013-11-23 00:47
- 题目描述:
- 统计一个数字在排序数组中出现的次数。
- 输入:
-
每个测试案例包括两行:
第一行有1个整数n,表示数组的大小。1<=n <= 10^6。
第二行有n个整数,表示数组元素,每个元素均为int。
第三行有1个整数m,表示接下来有m次查询。1<=m<=10^3。
下面有m行,每行有一个整数k,表示要查询的数。
- 输出:
-
对应每个测试案例,有m行输出,每行1整数,表示数组中该数字出现的次数。
- 样例输入:
-
- 8
- 1 2 3 3 3 3 4 5
- 1
- 3
- 8
- 样例输出:
-
- 4
- 题意分析:
题目要求在一个数组中找出一个数出现的次数,
第一种想法,当然是一次性全部数一遍,用map之类的结构保存统计结果,之后每次就可以log n复杂度查询了。时间复杂度为O(n) + m * O(log k),k是数组中不同元素的个数,空间复杂度O(k)。问题是——数组已经排序,这个特性没用到。
第二种想法,因为数组有序,所以每次都用二分查找找出一个数的左界和右界,然后right - left + 1即为结果。对于不存在的元素,二分当然返回-1之类的NOT_FOUND值,统计结果则为0。时间复杂度为m * O(log n),空间复杂度O(1)。
观察题目数据范围,数组长度n最大可以到10^6,查询次数m最大才10^3,如果采取上面方法一,O(n)则占了大头,不划算。所以选方法二。
其中bsearch_left求出target在数组a[]中的左下标,bsearch_right为右下标。这俩函数写法要小心,检查好数组指针,数据范围,左右端后才能开始二分查找。
查找到左右下标后,rr - ll + 1即为结果;查不到左右下标的话,结果为0。
- // 652724 zhuli19901106 1349 Accepted 点击此处查看所有case的执行结果 4932KB 1913B 720MS
- //
- #include <cstdio>
- using namespace std;
- int bsearch_left(const int a[], int n, int target)
- {
- int ll, rr, mm;
- if(a == NULL || n <= ){
- return -;
- }
- if(target < a[] || target > a[n - ]){
- return -;
- }
- // guarantee that a[left] < target && a[right] >= target
- if(target == a[]){
- return ;
- }
- ll = ;
- rr = n - ;
- while(rr - ll > ){
- mm = (ll + rr) / ;
- if(target > a[mm]){
- ll = mm;
- }else{
- rr = mm;
- }
- }
- if(a[rr] == target){
- return rr;
- }else{
- return -;
- }
- }
- int bsearch_right(const int a[], int n, int target)
- {
- int ll, rr, mm;
- if(a == NULL || n <= ){
- return -;
- }
- if(target < a[] || target > a[n - ]){
- return -;
- }
- // guarantee that a[left] <= target && a[right] > target
- if(target == a[n - ]){
- return n - ;
- }
- ll = ;
- rr = n - ;
- while(rr - ll > ){
- mm = (ll + rr) / ;
- if(target >= a[mm]){
- ll = mm;
- }else{
- rr = mm;
- }
- }
- if(a[ll] == target){
- return ll;
- }else{
- return -;
- }
- }
- int main()
- {
- int *a = NULL;
- int i, n, m;
- int target;
- int ll, rr;
- while(scanf("%d", &n) == ){
- if(n <= ){
- continue;
- }
- a = new int[n];
- for(i = ; i < n; ++i){
- scanf("%d", &a[i]);
- }
- scanf("%d", &m);
- for(i = ; i < m; ++i){
- scanf("%d", &target);
- ll = bsearch_left(a, n, target);
- if(ll < ){
- printf("0\n");
- continue;
- }
- rr = bsearch_right(a, n, target);
- if(rr < ){
- printf("0\n");
- continue;
- }
- if(rr >= ll){
- printf("%d\n", rr - ll + );
- }else{
- printf("0\n");
- }
- }
- delete[] a;
- a = NULL;
- }
- return ;
- }
剑指Offer - 九度1349 - 数字在排序数组中出现的次数的更多相关文章
- 剑指offer(37)数字在排序数组中出现的次数。
题目描述 统计一个数字在排序数组中出现的次数. 题目分析 这题用暴力解也可以过,不过面试官肯定期待更好的解法. 查找我们最熟悉的就是二分查找了,不过二分查找查找的数在数组中只有一个,我们这里却有很多个 ...
- 剑指offer三十七之数字在排序数组中出现的次数
一.题目 统计一个数字在排序数组中出现的次数. 二.思路 解法一:遍历数组计数 解法二:考虑到时有序数组,所以采用分查找,找到第一个K 和 最后一个K的位置, 二者相减. 三.代码 解法一: publ ...
- 【剑指Offer】37、数字在排序数组中出现的次数
题目描述: 统计一个数字在排序数组中出现的次数.例如,输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于数字3在该数组中出现了4次,所以函数返回4. 解题思路: 既然输入的数 ...
- 【剑指offer】题目38 数字在排序数组中出现的次数
思路: 应该是用二分查找分别找到该数字第一次和最后一次出现的位置,相减即可.O(logn) int findLeft(int a[], int n, int num) { , r = n - ; wh ...
- 剑指offer37:统计一个数字在排序数组中出现的次数
1 题目描述 统计一个数字在排序数组中出现的次数. 2 思路和方法 (1)查找有序数组,首先考虑使用二分查找,使时间复杂度为O(log n).更改二分查找的条件,不断缩小区间,直到区间头和区间尾均为k ...
- 九度OJ 1349 数字在排序数组中出现的次数 -- 二分查找
题目地址:http://ac.jobdu.com/problem.php?pid=1349 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数 ...
- 【Offer】[53-1] 【数字在排序数组中出现的次数】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 统计一个数字在排序数组中出现的次数.例如,输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出 ...
- 九度oj 1349 数字在排序数组中出现的次数
原题链接:http://ac.jobdu.com/problem.php?pid=1349 二分.. #include<algorithm> #include<iostream> ...
- 【剑指Offer面试编程题】题目1349:数字在排序数组中出现的次数--九度OJ
题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数组的大小.1<=n <= 10^6. 第二行有n个整数,表示数组元素,每个元素均 ...
随机推荐
- PHP 简单调用rest WebServices
<?php $ch = curl_init("http://api.cachk.com:8185/Tech-Trans.esPOS4.PosService.UAT/rest/enqui ...
- sql:表中数据全部删除之后,重新插入时,从1开始增加
数据库中设置了自增列,有时候需要清楚数据库从新录入数据.最常见的做法就是使用sql语句"delete 表明名"或是直接选中数据,然后删除数据.但是再次插入数据的时候,你就会发现自增 ...
- IIS7 http自动跳转到https(通过编辑Web.config实现)
本文摘自:https://www.cnblogs.com/wxbug/p/7054972.html 1.下载安装URL重写模块:Microsoft URL Rewrite Module 32位:htt ...
- April 20 2017 Week 16 Thursday
We are all in the gutter, but some of us are looking at the stars. 我们都生活在阴沟里,但仍有人仰望星空. In the past m ...
- 1923. Scary Politics (timus) (dfs) search
http://acm.timus.ru/problem.aspx?space=1&num=1923 -- timus This is s problem about thd dfs and s ...
- Entity Framework 6事务回滚
使用EF6你有新的事务处理可以使用类似于: 复制代码 using (var context = new PostEntityContainer()) { using (var dbcxtransact ...
- Uva 12299 带循环移动的RMQ(线段树)
题目链接:https://vjudge.net/contest/147973#problem/C 题意:传统的RMQ是一个不变的数组a求区间最值.现在要循环移动(往前移动). 分析:求区间问题,很容易 ...
- sqlserver 使用小技巧总结
1. 在数据库 查询中 在表名后面 加 英文字母,可以方便 查询 select a.name ,b.hobbynamefrom student as a, hobby as bwhere a ...
- MySQL与SQLServer的区别(一千条语句)
ER图.分页.差异.Java连接MySQL SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset LIMIT 子句可以被用于强制 ...
- p2597 灾难
我的思路 代码: #include<cstdio> #include<iostream> #include<algorithm> #include<vecto ...