<LeetCode OJ> 34. Search for a Range
2016-03-01 14:11
489 查看
34. Search for a Range
My SubmissionsQuestion
Total Accepted: 75021 Total
Submissions: 261472 Difficulty: Medium
Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return
[-1, -1].
For example,
Given
[5, 7, 7, 8, 8, 10]and target value 8,
return
[3, 4].
Subscribe to see which companies asked this question
Hide Tags
Array Binary
Search
Show Similar Problems
分析:
1,典型的二分法
算法:当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。基本思想:假设数据是按升序排序的,对于给定值key,从序列的中间位置k开始比较,
如果当前位置arr[k]值等于key,则查找成功;
若key小于当前位置值arr[k],则在数列的前半段 中查找;
若key大于当前位置值arr[k],则在数列的后半段中继续查找,直到找到为止。
时间复杂度:O(logn)。
上面的思想就是最最简单的二分法,即从一个排好序的数组之查找一个key值。 如下面的程序:
int search(int *arr, int n, int key)
{
int left = 0, right = n-1;
while(left<=right) {//慎重截止条件
int mid = left + ((right - left) << 1);//防止溢出
if (arr[mid] == key) //找到了
return mid;
else if(arr[mid] > key)
right = mid - 1;//给定值key一定在左边,并且不包括当前这个中间值
else
left = mid + 1;//给定值key一定在右边,并且不包括当前这个中间值
}
return -1;
}
这个程序,相信只要是一个合格的程序员应该都会写。 稍微注意一点, 每次移动left和right指针的时候,根据实际的意义在mid的基础上+1或者-1(两个指针总是会移动到一个未被比较过得新位置), 防止出现死循环, 那么问题来了,如果找不到关键值key什么时候截止呢?当left小于right的时候肯定要继续判断,那么问题就在于left==right是否要继续判断?当然要!前面说了,两个指针移动情况可以看出他们所指向的位置总是没有与key比较过,所以必须再进行一次比较,程序也就能够正确的运行。
2,二分法的两种变形
但如果条件稍微变化一下, 你还会写吗?其实,二分法真的不那么简单,尤其是二分法的各个变种。如,数组之中的数据可能可以重复,要求返回匹配的数据的最小(或最大)的下标;更近一步, 需要找出数组中第一个大于key的元素(也就是最小的大于key的元素的)下标,等等。 这些,虽然只有一点点的变化,实现的时候确实要更加的细心。 下面列出了这些二分检索变种的实现。
a. 找出第一个与key相等的元素
int searchFirstEqual(int *arr, int n, int key)
{
int left = 0, right = n-1;
while(left<=right) //相等时必须再判断一次,暂时理解为误差判断吧
{
int mid = (left+right)/2;
if(arr[mid] >= key)
right = mid - 1;//即使mid位置的值与key相等,我们也应该将其往左边移动,但是当前位置有可能是要找的位置
else if(arr[mid] < key)
left = mid + 1;//一定在mid位置的右边,并且不包括当前mid位置
}
if( left < n && arr[left] == key)
return left;
return -1;
}
b. 找出最后一个与key相等的元素
int searchLastEqual(int *arr, int n, int key)
{
int left = 0, right = n-1;
while(left<=right) {//相等时进行一次误差判断
int mid = (left+right)/2;
if(arr[mid] > key)
right = mid - 1;//key一定在mid位置的左边,并且不包括当前mid位置
else if(arr[mid] <= key)
left = mid + 1; //不相等一定在mid位置的右边,相等时答案有可能是当前mid位置
}
if( right>=0 && arr[right] == key)
return right;
return -1;
}
那么本题只需要分两步走即可,
1,寻找目标值的起始位置,找不到直接返回结果即可
2,寻找目标值的末尾位置,如果能到这一步一定可以找到末尾位置,大不了和其实位置一样嘛!
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { vector<int> result(2,-1); //一,寻找目标值的起始位置 int left = 0, right = nums.size()-1; while(left<=right) //相等时必须再判断一次,暂时理解为误差判断吧 { int mid = (left+right)/2; if(nums[mid] >= target) right = mid - 1;//即使mid位置的值与target相等,我们也应该将其往左边移动,但是当前位置有可能是要找的位置 else if(nums[mid] < target) left = mid + 1;//一定在mid位置的右边,并且不包括当前mid位置 } if( left < nums.size() && nums[left] == target) result[0]=left; else return result; //二,寻找目标值的末尾位置 right = nums.size()-1; while(left<=right) {//相等时进行一次误差判断 int mid = (left+right)/2; if(nums[mid] > target) right = mid - 1;//key一定在mid位置的左边,并且不包括当前mid位置 else if(nums[mid] <= target) left = mid + 1; //不相等一定在mid位置的右边,相等时答案有可能是当前mid位置 } if( right>=0 && nums[right] == target) result[1]= right; return result; } };
注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!
原文地址:http://blog.csdn.net/ebowtang/article/details/50772107
原作者博客:http://blog.csdn.net/ebowtang
本博客LeetCode题解索引:/article/3664871.html
相关文章推荐
- Conditional Sentences
- HTTP 1.1与HTTP 1.0的比较
- Oracle——备份与还原
- nginx配置使用笔记:三
- gedit 显示中文
- python的range和xrange的区别
- easyui 学习总结
- py2exe使用方法
- oracle_sql语句的大全
- static class 静态类(Java)
- 2016年会成为Java EE微服务年吗?
- 计算apk中方法数的脚本
- ComponentOne 2016 年产品规划
- android开发 wifi开发不稳定性测试
- c# from where select
- Codeforces #305 C. Mike and Frog 数论
- 60条Android日常开发总结的技术经验
- 5.5 单例模式实例
- CALayer3-层的属性
- 【maven】maven查找jar的步骤