算法合集 - 4

79 阅读2分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

滑动窗口

什么时候使用滑动窗口

字符串 - 找出该字符串中的某符合条件的子串

框架

主要思想在于:未能匹配到时,右侧指针滑动扩大范围。匹配到时,左侧指针滑动缩小范围

例题

二分搜索

什么时候使用二分搜索

搜索一个数,搜索左边界,搜索右边界

框架

注意mid和while

搜索一个数

闭区间 -

  1. while带等号
  2. 相等就返回
  3. mid必须加减一
  4. 全部结束返 -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中的所有元素,就会造成越界的情况。因此最后要判断是否越界:

寻找左边界
  1. 此时定义的搜索范围是闭区间[left, right]
  2. mid = left + (right - left) / 2;
  3. 如果nums[mid] < target - 左侧继续向右移 - left = mid + 1;
  4. 同理如果 nums[mid] > target - 右侧向左移动 - right = mid - 1;
  5. 由于是要找到左边界 - 因此如果中值与目标值匹配上,是将右指针继续向左偏移,看是否能找到最小的符合条件的左边界。 具体代码如下:
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;

寻找右边界

寻找右边界与左边界同理,只是判断和收缩的时候是左侧想向右移动。