1.题目描述:
统计一个数字在排序数组中出现的次数。
2.解题思路:
在一个已经排好序的数组中找一个数最先想到的应该是使用二分法查找,由于需要找的数是重复出现多次的,此时的二分查找需要一些技巧。注意到给出的数据类型是vector型,要找的数是k,可以通过查找k-0.5来确定比k-0.5大一点且最接近k-0.5的位置(此时如果k存在于数组中,该位置就是第一个k值得位置),再通过查找k+0.5,找到比k+0.5大一点且最接近k+0.5的位置(此时的位置是数组中距离k最近且比k大一点的数的位置)。
3.代码:
1 class Solution {
2 public:
3 int GetNumberOfK(vector<int> data ,int k) {
4 if(data.size() == 0)
5 {
6 return 0;
7 }
8 int left = sortnum(data, k-0.5);
9 int right = sortnum(data, k+0.5);
10 return right -left;
11 }
12 private:
13 int sortnum(vector<int> data, float k)
14 {
15 int size = data.size();
16 int left = 0;
17 int right = size - 1;
18 int mid = right/2;
19 for(int i = 0; i<size; i++)
20 {
21 if(data[mid] > k)
22 {
23 right = mid;
24 mid = left + (right - left)/2;
25 }
26 if(data[mid] < k)
27 {
28 left = mid;
29 mid = left + (right - left)/2;
30 }
31 if(right - left == 1)
32 return right;
33 }
34 return 0;
35 }
36 };
这种方法无法通过所有的测试用例,比如说:[3,3,3,3,4,5],3。32行的return right代码中在该测试用例下返回的是第二个3的位置,这是错误的,应该返回第一个3的位置。如果将其修改为return left,则碰到[3,4,5,5,5],5这种测试用例时又会返回倒数第二个5的位置。应该返回倒数第一个。
对上述问题进行分析,我们应该要找的是k-0.5与k+0.5在排序数组中应该插入的位置,因为这两个浮点数是我们构造出来的,在原数组中并不存在,所以二分查找的最终结果总是[a1,a2]。当a1不等于a2时,k-0.5位于a1与a2之间,就二分查找的左边情况来看,在data[mid]
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.size() == 0)
{
return 0;
}
int left = sortnum(data, k-0.5);
int right = sortnum(data, k+0.5);
return right - left;
}
private:
int sortnum(vector<int> data, float k)
{
int size = data.size();
int left = 0;
int right = size - 1;
int mid = right/2;
while(left<=right)
{
if(data[mid] > k)
{
right = mid-1;
mid = left + (right - left)/2;
}
if(data[mid] < k)
{
left = mid+1;
mid = left + (right - left)/2;
}
}
return left;
}
};