1. 数字在排序数组中出现的次数
NowCoder1
题目描述
统计一个数字在排序数组中出现的次数。
解题思路
1 二分法
看见有序,肯定就是二分查找了,算法比较简单。 值得一提的是,不要拘泥于递归,要会循环写法。
class Solution {
public:
int GetNumberOfK(vector<int> data, int k) {
int len = data.size();
if(!len) return 0;
int keyIdx = BiSearch(data, 0, len-1, k);
if(keyIdx == -1) return 0;
int cnt = 1, m = keyIdx-1, n = keyIdx+1;
while(m>=0 && data[m--]==k) cnt++;
while(n<len && data[n++]==k) cnt++;
return cnt;
}
int BiSearch(vector<int> data, int low, int high, int k) {
while(low <= high) {
int mid = (low+high)/2;
if(data[mid] == k) return mid;
else if(data[mid] < k) low = mid+1;
else high = mid-1;
}
return -1;
}
};
如果重复数字特别多,上面的方法就会很麻烦。因为data中都是整数,所以可以稍微变一下,不是搜索k的起始两个位置, 而是搜索k-0.5和k+0.5这两个数应该插入的位置,然后相减即可。(限于顺序)
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
return biSearch(data, k+0.5) - biSearch(data, k-0.5);
}
private:
int biSearch(const vector<int> & data, double num){
int s = 0, e = data.size()-1;
while(s <= e){
int mid = (e - s)/2 + s;
if(data[mid] < num) s = mid + 1;
else if(data[mid] > num) e = mid - 1;
}
return s;
}
};
还可以用相邻数定位置
class Solution {
public:
int GetNumberOfK(vector<int> data, int k) {
int first = binarySearch(data, k);
int last = binarySearch(data, k + 1);
return (first == data.size() || data[first] != k) ? 0 : last - first;
}
int binarySearch(vector<int> data, int k) {
int l = 0, h = data.size();
while (l < h) {
int m = l + (h - l) / 2;
if (data[m] >= k) h = m;
else l = m + 1;
}
return l;
}
};
2 其他低效办法
//大力出奇迹
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int count = 0;
for(int i=0;i<data.size();i++) if(data[i]==k) count++;
return count;
}
};
//虽然有违出题人的本意,但是。。。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
return count(data.begin(),data.end(),k);//单纯利用count函数。
}
};
//严谨一点。。。。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
auto left = lower_bound(data.begin(), data.end(), k);
auto right = upper_bound(data.begin(), data.end(), k);
return right - left;
}
};
2. 0~n-1中缺失的数字
题目描述
在一个长度为n-1的数组里的所有数字都是唯一的,且都在0到n-1的范围内。 因此,在0到n-1的范围内的n个数字中,有且只有一个数字不在该数组中,请找这个数字。
解题思路
1 暴力求和
用公式你n(n-1)/2求出在0到n-1的范围内的n个数字之和,接着求出数组中所有数字之和,两者作差即可。时间复杂度为O(n)。
2 二分法
in GetMissingNumber(vector<int> numbers) {
if(!numbers.size()) return -1;
int len = number.size(), left = 0, right = n-1;
while(left<=right) {
int mid = (right+left)/2;
if(numbers[mid] != mid) {
if(!mid || number[mid-1] == mid-1) return mid;
right = mid-1;
} else left = mid+1;
}
if(left == len) return len;
return -1;
}
3. 数组中数值和下标相等的元素
题目描述
假设一个单调递增的数组里每个元素都是整数并且是唯一的。请实现一个函数,找出数组中任意一个数值等于其下标的元素。(下标从0开始)
解题思路
二分法
int GetNumberSameAsIndex(vector<int> numbers) {
if(!numbers.size()) return -1;
int len = number.size(), left = 0, right = len-1;
while(left<right) {
int mid = left+((right-left)>>1);
if(numbers[mid] = mid) return mid;
else if(numbers[mid] > mid) right = mid-1;
else left = mid+1;
}
return -1;
}