这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战
滑动窗口
什么时候使用滑动窗口
字符串 - 找出该字符串中的某符合条件的子串
框架
主要思想在于:未能匹配到时,右侧指针滑动扩大范围。匹配到时,左侧指针滑动缩小范围
例题
二分搜索
什么时候使用二分搜索
搜索一个数,搜索左边界,搜索右边界
框架
注意mid和while
搜索一个数
闭区间 -
- while带等号
- 相等就返回
- mid必须加减一
- 全部结束返 -1。 mid = left + (Right - left)/2 而不用 mid = (left + Right)/2是为了防止栈溢出。
left = 0, Right = len(nums)-1
while(left <= Right):
mid = left + (Right - left)/2
if(nums[mid] == target):
return mid
elif(nums[mid] < target):
left = mid + 1
elif(nums[mid] > target):
Right = mid - 1
return -1
寻找左边界
寻找左右边界的意思就是找到target值后,返回对应的最左侧/最右侧边界。
寻找左边界的方式就是将右指针不断向左收缩,达到锁定左边界的目的。由于最终停止条件是left = Right + 1【Right = len(nums) - 1】,所以如果target大于nums中的所有元素,就会造成越界的情况。因此最后要判断是否越界:
寻找左边界
- 此时定义的搜索范围是闭区间[left, right]
- mid = left + (right - left) / 2;
- 如果nums[mid] < target - 左侧继续向右移 - left = mid + 1;
- 同理如果 nums[mid] > target - 右侧向左移动 - right = mid - 1;
- 由于是要找到左边界 - 因此如果中值与目标值匹配上,是将右指针继续向左偏移,看是否能找到最小的符合条件的左边界。 具体代码如下:
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
right = mid - 1;
}
}
判断越界
if (left >= nums.length || nums[left] != target)
return -1;
return left;
寻找右边界
寻找右边界与左边界同理,只是判断和收缩的时候是左侧想向右移动。