数组、链表

在处理数组和链表相关问题时,双指针技巧是经常用到的,
双指针技巧主要分为两类:左右指针快慢指针

例如:2sum

滑动窗口

一种特殊的双指针方法。
滑动窗口算法技巧主要用来解决子数组问题,比如让你寻找符合某个条件的最长/最短子数组。

  1. 初始化 left = right = 0,把索引左闭右开区间 [left, right) 称为一个「窗口」。
    2、先不断地增加 right 指针扩大窗口 [left, right),直到窗口中的字符串符合要求(包含了 T 中的所有字符)。
    3、此时停止增加 right,转而不断增加 left 指针缩小窗口 [left, right),直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。
    4、重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头

重点:
1、什么时候应该扩大窗口?

2、什么时候应该缩小窗口?

3、什么时候应该更新答案?

# 滑动窗口算法框架
def slidingWindow(s: str):
    # 用合适的数据结构记录窗口中的数据,根据具体场景变通
    # 比如说,我想记录窗口中元素出现的次数,就用 map
    # 我想记录窗口中的元素和,就用 int
    window = dict()
    
    left = 0
    right = 0
    while right < len(s):
        # c 是将移入窗口的字符
        c = s[right]
        window[c] = window.get(c, 0) + 1
        # 增大窗口
        right += 1
        # 进行窗口内数据的一系列更新
        #...

        #/*** debug 输出的位置 ***/
        # print(f"window: [{left}, {right})")
        #/********************/

        # 判断左侧窗口是否要收缩
        while left < right and "window needs shrink":
            # d 是将移出窗口的字符
            d = s[left]
            window[d] -= 1
            if window[d] == 0:
                del window[d]
            # 缩小窗口
            left += 1
            # 进行窗口内数据的一系列更新
            #...

单调栈

def nextGreaterElement(nums):
  stack = []  # 用于存储单调递增序列的栈
  result = [0] * len(nums)  # 初始化结果数组,所有元素先设为0(表示没有找到更大的元素)

  for i in range(len(nums)):
      # 当栈不为空且当前元素大于栈顶元素时,说明找到了一个比栈顶元素大的元素
      while stack and nums[i] > nums[stack[-1]]:
          # 将栈顶元素出栈,并更新结果数组
          result[stack.pop()] = nums[i]
      # 将当前元素索引入栈
      stack.append(i)
  
  # 处理右边没有更大元素的情况,将结果数组中未被更新的位置设为-1
  return [x if x != 0 else -1 for x in result]

# 示例
nums = [1, 7, 5, 9, 2, 5]
print(nextGreaterElement(nums))  # 输出: [7, 9, 9, -1, 5, -1]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容