【leetcode】二分、双指针高频题目整理

153 阅读3分钟

二分

  • 【33】搜索旋转数组

    • mid=target:直接返回
    • mid<right:左图情况
    • mid>left:右图情况
    • func search(nums []int, target int) int {
      l, r, mid := 0, len(nums)-1, 0
      for l <= r {
          mid = (l + r) / 2
          if nums[mid] == target {
              return mid
          }else if nums[mid]<nums[r]{
              if target>nums[mid] && target<=nums[r]{
                  l = mid + 1
              }else{
                  r = mid - 1
              }
          }else{
              if target>=nums[l] && target<mid{
                  r = mid-1
              }else{
                  l = mid+1
              }
          }
      }
      return -1
      }
      
  • 【153】寻找旋转排序数组中的最小值:二分,分两种情况

  • 【34】在排序数组中查找元素的第一个和最后一个位置:两次二分

  • 【74】搜索二维矩阵:两次二分

  • 【162】寻找峰值:二分,如果mid是峰值直接返回,否则向更高的地方走

二分答案

  • 【222】完全二叉树的节点个数:二分并验证是否有n个节点

双指针

两个指针或下标,在数组、链表上移动。时间复杂度O(n)。

同向移动(滑动窗口)

两指针从同一端移动到另一端

  • 【3】最长无重复子串:又指针移动并记录字母,如果有重复的就不断右移左指针
  • 【76】最小覆盖子串:又指针移动并记录字母,如果满足覆盖就不断更新答案并右移左指针
  • 【209】长度最小的子数组:找出该数组中满足其和 ≥ target 的长度最小的 连续子数组
  • 【offer 48】最长不含重复字符的子字符串:右指针记录数,当出现重复值,左指针右移删除
  • 【424】替换后的最长重复字符:滑动窗口时,枚举变成各种相同字母的最长结果
  • 【567】字符串的排列:hash记录第一个字符串所有字母和数目,又指针向右走,遇到有的计数减一,计数边负或者遇到没有的就把左指针右移。
  • 【611】有效三角形的个数:排序,枚举第一个数,和第二个数,第三个数为一个向右走的指针,符合两边之和大于第三边就向右走
  • 合并两个有序数组、链表
  • 原地删除数组的重复值

反向移动

从两端向中间逼近答案

  • 【11】盛最多水的容器:不断计算体积,向中间移动短的那个

  • 【15】三数之和:排序,枚举第一个数,剩下两个数lr向中间找

  • 【42】接雨水:先移动短板的那边,更新短板和计算是否有雨水

  • 有序数组上两数之和

  • 最接近的三数之和:排序+有序数组的两数之和

  • 【18】四数之和:排序+双重for+双指针

  • 【167】两数之和 II - 输入有序数组:有序数组两数之和

快慢指针

  • 【141】环形链表:快慢指针从头开始走,快指针走两步,慢指针走一步,会在环的入口处相遇

    • 为什么会相遇,在环内,快指针每次比慢指针快一步,一定会赶上

    • 为什么在入口相遇:假设总长度n,环外长度x,环内长度n-x

      • 当low到入口时,low坐标0,fast坐标x%(n-x)
      • fast还需要n-x-x%(n-x)步赶上low
      • 经过n-x-x%(n-x)步后,fast在n-x%(n-x)=0的位置上,正好是起点