69. x 的平方根

思路:运用二分查找的方法,将上下界分别定为0和x。循环内仅分2种情况,直至不满足循环的条件而退出循环。
int mySqrt(int x){
if(x == 0)
return x;
int Left,Right,mid,index;
Left = 0; Right = x; index = -1;
while(Left <= Right){
mid = Left + (Right - Left) / 2;
if((long long)mid*mid <= x){//注意范围,避免溢出
index = mid;
Left = mid + 1;
}
else
Right = mid - 1;
}
return index;
}
34. 在排序数组中查找元素的第一个和最后一个位置

一开始我的思路是找到target最后一次出现的下标,然后利用for循环往前找,知道遇到不是target的数(这样做是因为给的数组是按升序排列的),代码如下:
int* searchRange(int* nums, int numsSize, int target, int* returnSize){
int left,right,mid,startindex,endindex;
left = 0; right = numsSize-1; startindex = endindex = -1;
int *indexarray = malloc(sizeof(int) * 2);
*returnSize = 2;
while(left <= right){//找到最后一次出现的下标的后一位
mid = left + (right - left) / 2;
if(nums[mid] >= (target + 1))
right = mid;
else
left = mid + 1;
}
endindex = left;
if(endindex != -1){//if成立说明存在target
endindex -= 1;
startindex = endindex;
for(int i = endindex-1; i>=0; i--){
if(nums[i] != target)
break;
startindex = i;
}
indexarray[0] = startindex;
indexarray[1] = endindex;
}
else{
indexarray[0] = -1;
indexarray[1] = -1;
}
return indexarray;
}
这样做样例估计都能过,但超时了,问题大概率是出在后面的for循环上(最坏的情况是数组所有的数都是target目标值,这样一来时间复杂度就为O(n),而题目要求时间复杂度为O(log n)。
所以我不得不分别用二分法来求target第一次出现的下标和target最后一次出现下标的后一位,用两个函数来实现,代码如下:
int* searchRange(int* nums, int numsSize, int target, int* returnSize){
int left,right,mid,startindex,endindex;
int *indexarray = malloc(sizeof(int) * 2);
*returnSize = 2;
indexarray[0] = indexarray[1] = -1;
startindex = FirstIndex(nums,numsSize,target);
endindex = LastIndex(nums,numsSize,target) - 1;
if(startindex == numsSize || nums[startindex] != target)//没找到的情况
return indexarray;
indexarray[0] = startindex;
indexarray[1] = endindex;
return indexarray;
}
//找到target第一次出现的下标
int FirstIndex(int* nums, int numsSize, int target){
int left,right,mid;
left = 0; right = numsSize - 1;
while(left <= right){
mid = left + (right - left) / 2;
if(nums[mid] >= target)
right = mid;
else
left = mid + 1;
}
return left;
}
///找到target最后一次出现下标的后一位
int LastIndex(int* nums, int numsSize, int target){
int left,right,mid;
left = 0; right = numsSize - 1;
while(left <= right){
mid = left + (right - left) / 2;
if(nums[mid] > target)//与上面的差别:相等的情况放在else里了
right = mid;
else
left = mid + 1;
}
return left;
}
然而这样又又超时了!(淦!)检查了、修改了不知道多少次之后终于被我试出来了!
把两个子函数里的right初值改为numsSize,while的条件的等号拿掉,就行了!所以正确代码为:
int* searchRange(int* nums, int numsSize, int target, int* returnSize){
int left,right,mid,startindex,endindex;
int *indexarray = malloc(sizeof(int) * 2);
*returnSize = 2;
indexarray[0] = indexarray[1] = -1;
startindex = FirstIndex(nums,numsSize,target);
endindex = LastIndex(nums,numsSize,target) - 1;//得到的是target最后一次出现下标的后一位
if(startindex == numsSize || nums[startindex] != target)
return indexarray;
indexarray[0] = startindex;
indexarray[1] = endindex;
return indexarray;
}
//找到target第一次出现的下标
int FirstIndex(int* nums, int numsSize, int target){
int left,right,mid;
left = 0; right = numsSize;
while(left < right){
mid = left + (right - left) / 2;
if(nums[mid] >= target)
right = mid;
else
left = mid + 1;
}
return left;
}
///找到target最后一次出现下标的后一位
int LastIndex(int* nums, int numsSize, int target){
int left,right,mid;
left = 0; right = numsSize;
while(left < right){
mid = left + (right - left) / 2;
if(nums[mid] > target)//与上面的差别:相等的情况放在else里了
right = mid;
else
left = mid + 1;
}
return left;
}
原理暂时还没搞懂......
这篇博客介绍了如何使用二分查找算法在排序数组中查找目标元素的第一个和最后一个位置。首先尝试通过一次二分查找找到目标值的最后出现位置,然后回溯找到第一个出现的位置。原始代码存在效率问题,经过优化,将二分查找应用于两个子问题,提高了时间复杂度至O(logn),解决了超时问题。

5758

被折叠的 条评论
为什么被折叠?



