二分查找及其变化应用
2017-08-01 23:04
232 查看
经典的二分查找
两次二分查找
题:统计一个数字在排序数组中出现的次数。例如输入排序数组{1, 2, 3, 3, 3, 3, 4, 5}和数字3,由于3在这个数组中出现了4次,因此输出4。分析:对于该题,如果直接遍历很容易得到出现的次数,但是其时间复杂度为O(N)。因为数组是排序的所以我们可以考虑二分查找来加快速度。通过二分查找分别找到最左边的3和最右边的3位置,就可以计算得到3的个数,算法复杂度为O(logN)
#include <vector> #include <iostream> using namespace std; class Solution { public: int GetNumberOfK(vector<int> data ,int k) { if(data.empty()) return 0; int firstPos = GetFirstPos(data, k, 0, data.size() - 1); int lastPos = GetLastPos(data, k, 0, data.size() - 1); if((firstPos == -1) || (lastPos == -1)) return 0; else return lastPos - firstPos + 1; } int GetFirstPos(vector<int>& data, int k, int left, int right){ if(left > right) return -1; int ret; int center = (left + right) >> 1; if(data[center] < k){ ret = GetFirstPos(data, k, center + 1, right); } else if(data[center] > k){ ret = GetFirstPos(data, k, left, center - 1); } else{ if(center == 0) return 0; if(data[center - 1] != k) return center; else ret = GetFirstPos(data, k, left, center - 1); } return ret; } int GetLastPos(vector<int>& data, int k, int left, int right){ int center = (left + right) >> 1; while(left <= right){ if(data[center] < k) { left = center + 1; } else if(data[center] > k) { right = center - 1; } else { if((center + 1) < static_cast<int>(data.size()) && data[center + 1] == k) left = center + 1; else return center; } center = (left + right) >> 1; } return -1; } }; int main() { Solution obj; vector<int> input = {3, 3, 3, 3, 4, 5}; int ret = obj.GetNumberOfK(input, 3); cout << ret << endl; return 0; }
相关文章推荐
- 巩固基础篇:经典二分查找模型及其应用
- 二分查找及其应用
- 利用循环不变式写出正确的二分查找及其衍生算法
- uva11991(二分查找或map的应用)
- 二分查找之美:二分查找及其变体的正确性以及构造方式
- 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式
- C++二分查找在搜索引擎多文档求交的应用分析
- 二分查找及其变形总结
- 剑指Offer--数组在排序数组中出现的次数--二分查找的应用
- Scala深入浅出进阶经典 第50讲:Scala中Variance变化点及其在Spark中的应用源码解析
- POJ 3273 Monthly Expense 二分查找的应用
- 二分查找 (最经典代码,及其边界条件的实践分析)
- 二分查找突破上下限,树状数组的三种应用。
- 二分查找及其变形算法
- 双重二分查找的应用
- 二分查找的变形应用
- 二分查找之应用篇
- Split Array Largest Sum 二分查找应用 C实现
- 二分查找的应用
- 二分查找的灵活应用