问题导入
给定一个升序排列的数组以及一个目标整数,要求返回该数在数组中的角标范围,若不存在则返回[-1,-1]. 要求算法的时间复杂度不超过O(logN).
一般求解
先考虑数组可能为空的特殊状况,排除之后将返回值初始化为给定数组的范围,逐渐向内逼近即可.
这种算法虽然进行了两次循环,但真正循环的次数一定是小于等于数组长度的,所以满足题目对时间复杂度的要求.然而查找目标值的方法是遍历,效率比较低下.class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { vector<int> rtn(2, -1); int begin = 0, end = nums.size()-1; if (end < 0) return rtn; while (nums[begin] < target) begin++; while (nums[end] > target) end--; if (begin > end) return rtn; rtn.clear(); rtn.push_back(begin); rtn.push_back(end); return rtn; } };
查找优化
在已完成排序的数组中进行对特定值的查找,二分法无疑是最为优秀的.这里fork到一份二分递归查找的代码,以供学习参考.class Solution { public: typedef vector<int> VI; void recur(VI & v,int T,int i,int j,VI & ans) { if ( i>j ) return; if ( i==j ) { if ( v[i]==T ) { if ( ans[0]==-1 || i<ans[0] ) ans[0]=i; if ( ans[1]==-1 || i>ans[1] ) ans[1]=i; } return; } int mid(i+(j-i)/2); if ( v[mid]<T ) recur(v,T,mid+1,j,ans); else if ( v[mid]>T ) recur(v,T,i,mid-1,ans); else { recur(v,T,i,mid,ans); recur(v,T,mid+1,j,ans); } } vector<int> searchRange(vector<int>& v, int T) { VI ans(2,-1); recur(v,T,0,v.size()-1,ans); return ans; } };