返回

滑窗算法:「前端面试」12 个问题,让你对面试更加有信心!

前端

滑动窗口算法:掌握面试中的利器

在软件开发面试中,算法问题是常见的考察重点,而滑动窗口算法更是面试官青睐的考题之一。掌握滑动窗口算法,不仅能增强你的面试信心,还能为实际工作中解决问题提供有力工具。

什么是滑动窗口算法?

滑动窗口算法是一种高效的算法技术,适用于处理连续数据流的问题。它通过维护一个窗口,在这个窗口内移动和处理数据,实现对数据序列的逐步计算。

滑动窗口算法的优点

  • 窗口大小可调,灵活应对不同数据规模;
  • 时间复杂度低,通常为线性时间;
  • 适用于在线处理和实时计算场景。

12个经典的滑动窗口算法问题

  1. 连续子数组的最大和
    代码示例:

    def max_subarray_sum(arr):
        max_sum = float('-inf')
        cur_sum = 0
        for num in arr:
            cur_sum = max(num, cur_sum + num)
            max_sum = max(max_sum, cur_sum)
        return max_sum
    
  2. 最长无重复子字符串
    代码示例:

    def longest_substring_without_repeating_chars(s):
        char_index_map = {}
        max_length = 0
        start = 0
        for end, char in enumerate(s):
            if char in char_index_map and char_index_map[char] >= start:
                start = char_index_map[char] + 1
            char_index_map[char] = end
            max_length = max(max_length, end - start + 1)
        return max_length
    
  3. 最长公共子字符串
    代码示例:

    def longest_common_substring(str1, str2):
        dp = [[0 for _ in range(len(str2) + 1)] for _ in range(len(str1) + 1)]
        max_length = 0
        for i in range(1, len(str1) + 1):
            for j in range(1, len(str2) + 1):
                if str1[i - 1] == str2[j - 1]:
                    dp[i][j] = dp[i - 1][j - 1] + 1
                    max_length = max(max_length, dp[i][j])
        return max_length
    
  4. 最长回文子字符串
    代码示例:

    def longest_palindromic_substring(s):
        max_length = 0
        start = 0
        for i in range(len(s)):
            for j in range(i + 1, len(s) + 1):
                if is_palindrome(s[i:j]) and j - i > max_length:
                    max_length = j - i
                    start = i
        return s[start:start + max_length]
    
  5. 最长连续子序列和
    代码示例:

    def longest_consecutive_subsequence(arr):
        count = 0
        max_count = 0
        num_set = set(arr)
        for num in num_set:
            if num - 1 not in num_set:
                curr_count = 1
                while num + curr_count in num_set:
                    curr_count += 1
                max_count = max(max_count, curr_count)
        return max_count
    
  6. 最长递增子序列
    代码示例:

    def longest_increasing_subsequence(arr):
        dp = [1] * len(arr)
        max_length = 1
        for i in range(1, len(arr)):
            for j in range(i):
                if arr[i] > arr[j]:
                    dp[i] = max(dp[i], dp[j] + 1)
            max_length = max(max_length, dp[i])
        return max_length
    
  7. 最长递减子序列
    代码示例:

    def longest_decreasing_subsequence(arr):
        dp = [1] * len(arr)
        max_length = 1
        for i in range(len(arr) - 1, -1, -1):
            for j in range(i + 1, len(arr)):
                if arr[i] > arr[j]:
                    dp[i] = max(dp[i], dp[j] + 1)
            max_length = max(max_length, dp[i])
        return max_length
    
  8. 最大子矩阵和
    代码示例:

    def max_submatrix_sum(matrix):
        rows, cols = len(matrix), len(matrix[0])
        max_sum = float('-inf')
        for start_row in range(rows):
            prefix_sum = [0] * cols
            for end_row in range(start_row, rows):
                for col in range(cols):
                    prefix_sum[col] += matrix[end_row][col]
                max_sum = max(max_sum, max_subarray_sum(prefix_sum))
        return max_sum
    
  9. 最长无重复元素子数组
    代码示例:

    def longest_subarray_without_repeating_elements(arr):
        char_index_map = {}
        max_length = 0
        start = 0
        for end, char in enumerate(arr):
            if char in char_index_map and char_index_map[char] >= start:
                start = char_index_map[char] + 1
            char_index_map[char] = end
            max_length = max(max_length, end - start + 1)
        return max_length
    
  10. 最长上升下降子序列
    代码示例:

    def longest_alternating_subsequence(arr):
        n = len(arr)
        dp = [[1] * 2 for _ in range(n)]
        for i in range(1, n):
            for j in range(i):
                if arr[i] > arr[j] and dp[i][0] < dp[j][1] + 1:
                    dp[i][0] = dp[j][1] + 1
                elif arr[i] < arr[j] and dp[i][1] < dp[j][0] + 1:
                    dp[i][1] = dp[j][0] + 1
        return max(max(row) for row in dp)
    
  11. 最短覆盖子数组
    代码示例:

    def min_subarray_cover(arr, target):
        start, end = 0, 0
        min_len = float('inf')
        window_sum = 0
        while end < len(arr):
            window_sum += arr[end]
            while window_sum >= target:
                if end - start + 1 < min_len:
                    min_len = end - start + 1
                    min_start, min_end = start, end
                window_sum -= arr[start]
                start += 1
            end += 1
        return min_len if min_len != float('inf') else 0
    
  12. 最小窗口子字符串
    代码示例:

    def min_window(s, t):
        if len(s) < len(t): return ""
        char_freq = {}
        for char in t:
            char_freq[char] = char_freq.get(char, 0) + 1
        window_start = 0
        matched_count = 0
        min_window_len = float('inf')
        min_window_start = 0
        for window_end, char in enumerate(s):
            if char in char_freq:
                char_freq[char] -= 1
                if char_freq[char] >= 0:
                    matched_count += 1
            while matched_count == len(t):
                if window_end - window_start + 1 < min_window_len:
                    min_window_len = window_end - window_start + 1
                    min_window_start = window_start
                char_left = s[window_start]
                if