704. 二分查找
二分法于我学习算法而言如同abandon于我学习有序英语单词,每每拾起算法都会从二分法开始学习。经过多次学习,这是我最喜欢的二分法讲解
下面是根据上面的讲解去做题实践中得出的三个要点
1. 循环中止条件为不满足while(left < right)
这并不代表什么开闭区间,单纯的为循环条件。当 left
与 right
重合的时候,我们就找到了问题的答案,使用这种写法有一个巨大的好处,那就是返回值不需要考虑返回 left
还是 right
,因为退出循环以后,它们是重合的。
2. 根据实际情况缩小搜索区间
二分查找只有一个思想,那就是:逐步缩小搜索区间。根据mid索引对应的数组值与target的关系,结合题意,确定下一个搜索区间。有[left, mid - 1][mid, right]和[left, mid][mid + 1, right]两种确定下一个搜索区间的写法。
3. 根据搜索区间写法判断在计算mid时是否需要加1
由于系统在计算整型变量时是向下取整的,设想最后只剩下两个相邻的索引,此时计算mid值一定会得出left的值,若是[left, mid - 1][mid, right]这种下一搜索区间,会出现死循环,因此在此种下一搜索区间的写法里,计算mid值时需要加1。
int search(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize - 1;
int mid;
int Ret = -1;
while(left < right)
{
mid = left + (right - left)/2;
if(nums[mid] < target)
{
left = mid + 1;
}
else
{
right = mid;
}
}
if(nums[left] == target)
{
Ret = left;
}
return Ret;
}
27.移除元素
双指针。fast指针遍历数组中的元素,若fast索引对应的值不等于val,将此时fast索引对应的值赋给slow索引的数组值,slow索引加1;若Fast索引对应的值等于val,无事发生。
最终数组中的等于val的值都被后面索引的值覆盖,slow的值为剩余的数组长度的值
int removeElement(int* nums, int numsSize, int val){
int fast = 0, slow = 0;
while(fast < numsSize)
{
if(nums[fast] != val)
{
nums[slow++] = nums[fast];
}
fast++;
}
return slow;
}