leetcode题目
- 407 简单题 二分查找
- 35.搜索插入位置
- 34.在排序数组中查找元素的第一个和最后一个位置 (这个有难度)
- 69.x 的平方根
- 367.有效的完全平方数
这种类型的题不算难,但是最难的是边界处理的判断问题。
以后大家只要看到面试题里给出的数组是有序数组,都可以想一想是否可以使用二分法。(最好题目中出现无重复元素)
确定要查找的区间到底是左闭右开[left, right),还是左闭又闭[left, right],这就是不变量。
主要能清楚这一点 ,因为这两个区间会有两个不一样的模板。
循环不变量:是一组循环体内,每次迭代均保持为真的某种性质。
必须遵循以下三个属性:
初始化:在循环第一次迭代之前,循环不变量为真。
保持: 如果在循环的一次迭代之前循环不变量为真,那么在下一次迭代之前循环不变量同样为真
终止:当循环结束时,不变量能够提供有用的属性,帮助我们证实算法的正确。
必须保证循
环结束时”循环不变量“和"循环终止条件"同时成立
func insertionSort(vector<int>& nums) {
int j = 0,n = nums.size();
while (j < n) {
int i = j - 1;
int key = nums[j];
if (i >= 0 && nums[i] > key) {
nums[i+1] = nums[i];
i--;
}
nums[i+1] = key;
j++;
}
}
循环不变量: j
之前(不包含nums[j]
)的元素已经排好序(升序)。
- 初始化:
j
为0
,表示目前排好序的子数组没有元素,不变式成立。 - 保持: 如果前一轮迭代
j
满足条件,则[0,j)
范围内子数组的元素均为升序。当前迭代中nums[j+1]
与子数组的元素从大到小进行对比。如果找到第一个比nums[j+1]
小的元素,则在其后插入一个值为nums[j+1]
的元素。因此在此次迭代结束后,[0,j+1)
范围内子数组的元素均为升序,不变式成立。 - 终止:
j
不断递增,当j == n
时,所有数组的元素均被遍历处理,此时[0,n)
为升序,不变式成立。
第一种方法
-
while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
-
if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
第二种方法
-
while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
-
if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
对于69题
对于浮点二分的基础思想代码:
对于367题
我个人觉得这些被列为二分查找,所以我做这道题也是在69题的基础浮点二分的基础上按其规则进行改的,当然题目中没有说不能调用库函数,可以直接调用sqrt()库函数,这样很方便。