以剑指offerⅡ 068 查找插入位置为例:
给定一个排序的整数数组 nums 和一个整数目标值 target ,请在数组中找到 target ,并返回其下标。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
示例 4:
输入: nums = [1,3,5,6], target = 0
输出: 0
示例 5:
输入: nums = [1], target = 0
输出: 0
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 为无重复元素的升序排列数组
-104 <= target <= 104
标准的二分查找位置,因为题目给出的时间复杂度为O(log n)
代码为
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
// cout << target << endl;
// int left = 0;
// int right = nums.size()-1;
// int i = 1;
// while(left < right)
// {
// int middle = (left + right)/2;
// cout << "i=" << i++ << endl;
// cout << "l=" << left << endl;
// cout << "r=" << right << endl;
// cout << "middle:" << middle << endl;
// // if(middle == 0)
// // {
// // if(nums.size() == 1)
// // {
// // if(target <= nums[0])
// // return 0;
// // else
// // return 1;
// // }
// // else if(nums.size() == 2)
// // {
// // if()
// // }
// // }
// if(nums[middle] == target)
// {
// cout << 1 << endl;
// while(nums[middle-1] == nums[middle] && middle >= 1)
// {
// middle -= 1;
// }
// cout << "JIEGUO:" << middle << endl;
// return middle;
// }
// else if(nums[middle] < target)
// {
// left = middle + 1;
// cout << 2 << endl;
// }
// else
// {
// right = middle;
// cout << 3 << endl;
// }
// }
// cout << "结果:" << left << endl;
// return left;
int l = 0;
int r = nums.size() - 1;
while(l < r)
{
int mid = (l + r)/2;
if(nums[mid] >= target)
r = mid;
else
l = mid+1;//左闭右开
}
return l == nums.size() - 1 && nums[l] < target ? l+1 : l;
}
};
代码如下,前面注释掉的代码为本人第一次尝试与调试结果。
当时本人想如果找到nums[middle] = target
就向左遍历,直到没有相等的,因为要把新数据放在最左边。
但难以处理middle=0的情况。
所以采用下面的方法,不管target等于多少,一定要保证他在[left,right)这样的一个新的左闭右开区间中,最终单独判断一下最右边的情况就行。