力扣总结-数组

144 阅读5分钟

二分法

二分法,常用于在有序数组中,查找某个目标

  1. arr[i] == target
  2. j < i && arr[j] != target
  3. k > i && arr[k] != target

双指针

问题:常用于数组原地修改删除操作,实现O(1)的空间复杂度,O(N)的时间复杂度
本质:一个指针A用于遍历,一个指针B用于维护具有某种特点的目标子数组
要点:思考清楚指针B维护的目标子数组具有什么特点,并想清楚B的移动时机与方法

  • 27. 移除元素 - eary 目标子数组特点:不包含待移除元素
    B的移动时机与方法:当A发现当前元素非待移除元素,将当前元素添加到目标子数组,B向后移
  • 26. 删除有序数组中的重复项 - easy 目标子数组特点:不包含重复项
    B的移动时机与方法:当A发现当前元素与前一个元素不相同时,将当前元素添加到目标子数组,B向后移
    特殊逻辑:由“B的移动时机与方法”可知,A在遍历数组时,需要知道上一个元素,所以需要另外一个全局变量维护这个状态
  • 283. 移动零- easy 目标子数组特点:不包含0
    B的移动时机与方法:当A发现当前元素为非0元素时,将当前元素添加到目标子数组,B向后移
  • 844. 比较含退格的字符串 - easy 目标子数组特点:不包含退格字符
    B的移动时机与方法:当A发现当前元素为非退格字符时,将当前元素添加到目标子数组中,B向后移;当A发现当前元素为退格字符时,B向前移
  • 977. 有序数组的平方 - easy 双指针向内推进,对应平方逐渐减小,逐渐逼近0,双指针碰面循环结束

滑动窗口

问题:基于给定数组,求满足某种条件的子数组,O(1)空间复杂度,O(N)时间复杂度
本质:通过两个指针A/B,定义一个窗口(子数组[A,B]),移动A/B,在窗口一定的约束下,达到某个目标最优解
要点:想清楚约束和目标最优解是什么,A/B的移动时机和方向

  • 209. 长度最小的子数组 - mid 约束:窗口内元素和大于目标值
    目标最优解:窗口要尽可能的小
    A/B的移动时机和方向
    B向右移,窗口元素和逐渐增大,直至大于目标值为止。
    此时,窗口满足约束;若B向右移或A向左移,则约束满足但窗口增大,离目标最优解越来越远;若B向左移,不满足约束,因此只能A向右移
    A右移,若满足约束,则当前解优于A不右移的解,若不满足约束,只能将B右移使窗口满足约束
    特殊逻辑:要维护一个状态,保存当前找到的最优解,当每次满足约束时,与当前找到的最优解比较并更新最优解
  • 904.水果成篮 - mid 约束:窗口内只能又两个数字
    目标最优解:窗口要尽可能的大
    A/B的移动时机和方向
    窗口内两个元素为D1/D2,A指向数组内第一个等于D1的元素,B向右遍历,寻找第一个不等于D1也不等与D2的元素。遍历过程中,不断更新最优解。
    若B找到第一个不等于D1也不等与D2的元素,此时需要更新D1/D2,D2更新为B指向当前元素,D1指向B指向前一个元素,同时更新A指针,B再次向右遍历。
    特殊逻辑:需要维护一个状态,用来保存当前找到的最优解,当每次满足约束时,与当前找到的最优解比较并更新最优解
  • 76. 最小覆盖子串 - hard 约束:窗口内包含t中所有的字符,并且对于t中重复字符,窗口中该字符数量必须不少于t中该字符数量
    目标最优解:窗口要尽可能的小
    A/B的移动时机和方向
    B右移,窗口内元素越来越多,直到对于t中每个字符,窗口内该字符的个数都是大于等于t中个数。 此时,窗口满足约束,若B右移,或者A左移,则满足约束但窗口增大,距离目标最优解越来越大;若B左移,则不满足约束,因此,只能A右移。 A右移,窗口内元素减少,若对于t中每个字符,窗口内该字符的个数仍然都是大于等于t中个数,则更新最优解,否则,窗口不满足约束,右移B,使窗口满足约束。 特殊逻辑
    需要维护一个状态,用来保存当前找到的最优解,当每次满足约束时,与当前找到的最优解比较并更新最优解
    校验当前窗口是否满足约束,需要保存t中每个字符的个数,并记录当前窗口的每个字符的个数

其他