返回

算法和数据结构面试题(JavaScript+Python)——滑动窗口

闲谈

滑动窗口算法:一种高效查找数组子序列的技巧

什么是滑动窗口算法?

滑动窗口算法是一种高效的编程技术,用于在数组或列表中查找连续子序列,这些子序列满足某些特定条件。它的本质就像一个窗口,在这个窗口内收集信息,随着窗口在数组中滑动,信息也会随之更新。滑动窗口算法避免了重复循环元素,特别适用于计算总和或其他数值操作。

滑动窗口算法的实现

滑动窗口算法可以基于数组或链表实现:

  • 基于数组的实现: 使用两个指针标记窗口的左右边界,移动指针即可更新窗口内的元素。
  • 基于链表的实现: 使用链表存储窗口内的元素,删除头部元素并添加尾部元素即可更新窗口。

滑动窗口算法的应用场景

滑动窗口算法在实际应用中十分广泛,例如:

  • 查找数组中连续子序列的和等于特定值的子序列
  • 查找数组中连续子序列的积等于特定值的子序列
  • 查找数组中连续子序列的最大值或最小值
  • 查找数组中连续子序列的平均值

滑动窗口算法的优势

滑动窗口算法具有以下优势:

  • 高效:避免重复遍历数组元素,提高计算效率。
  • 适用性强:适用于查找数组中满足特定条件的连续子序列。

JavaScript 示例

function maxSlidingWindow(nums, k) {
  if (nums.length < k) {
    return [];
  }
  const result = [];
  const queue = [];
  for (let i = 0; i < nums.length; i++) {
    while (queue.length > 0 && nums[queue[queue.length - 1]] <= nums[i]) {
      queue.pop();
    }
    queue.push(i);
    if (i >= k - 1) {
      result.push(nums[queue[0]]);
      if (queue[0] === i - k + 1) {
        queue.shift();
      }
    }
  }
  return result;
}

Python 示例

def maxSlidingWindow(nums, k):
  if len(nums) < k:
    return []
  result = []
  queue = []
  for i in range(len(nums)):
    while queue and nums[queue[-1]] <= nums[i]:
      queue.pop()
    queue.append(i)
    if i >= k - 1:
      result.append(nums[queue[0]])
      if queue[0] == i - k + 1:
        queue.pop(0)
  return result

常见问题解答

1. 滑动窗口算法与常规循环遍历有什么区别?

滑动窗口算法避免了重复循环元素,而常规循环遍历需要遍历数组中的每个元素。

2. 滑动窗口算法何时不适用?

当问题要求遍历数组中的所有值时,滑动窗口算法不适用。

3. 滑动窗口算法如何处理有重复元素的数组?

对于有重复元素的数组,滑动窗口算法可能需要额外的处理来确保窗口内的元素不重复。

4. 滑动窗口算法如何处理负数元素?

对于包含负数元素的数组,滑动窗口算法可能需要特殊处理以确保结果的正确性。

5. 滑动窗口算法在时间复杂度上的表现如何?

滑动窗口算法的时间复杂度通常为 O(n),其中 n 为数组的长度。