Interesting Algorithm: Understanding and Application of Sliding Window Algorithm

foreword

In programming and data structures, sliding window algorithms are a common problem-solving method. It is primarily used for problems involving consecutive or fixed-length subarrays, subsequences, or substrings. This article will discuss the sliding window algorithm in depth, including its basic concepts, application scenarios, basic steps and specific Java code practices.

1. Introduction to sliding window algorithm

The sliding window algorithm is an optimization technique that is mainly used to solve subsequence or substring problems in arrays or linked lists. Its main advantage is the ability to reduce the time complexity of some complex problems to linear.

2. Application Scenarios of Sliding Window Algorithm

The sliding window algorithm has a wide range of applications, and it is often used to solve problems involving continuous or fixed-length subarrays, subsequences, or substrings. Here are some specific examples:

  • Maximum/minimum subsequence problems in arrays : e.g., "Maximum contiguous subarray sum", "Minimum covering substring", etc. These problems usually need to find a continuous subinterval in an array or string, so that it satisfies certain conditions (such as the largest or smallest sum, or contains all specified characters, etc.).

  • Fixed-length subsequence problems : For example, "a substring of non-repeating characters of length K", "a continuous subarray of sum K", etc. These problems usually require finding subsequences of fixed or variable length that satisfy certain conditions.

  • Counting questions : For example, "the number of subarrays whose sum is K", "all anagrams", etc. This type of problem requires counting the number of subarrays or substrings that satisfy certain conditions.

The power of the sliding window algorithm is that it can convert these seemingly complex problems into linear complexity, which greatly improves the operating efficiency of the algorithm. After understanding the basic principle of sliding window, we can flexibly apply it to solve various problems.

Three, the basic steps of the sliding window algorithm

The sliding window algorithm usually involves the following core steps:

  1. Initialize a window : A window is usually represented as a continuous subrange in an array or a string, and two pointers (such as left and right) can be used to represent its boundary. Initially, this window can be empty, or contain one or more elements.

  2. Moving the window : Depending on the specific problem, it may be necessary to move the left border of the window to the right (shrinking the window), or to move the window's

Right border (enlarges window). The movement of the window will change the elements in the window.

  1. Update the result according to the change of the window : every time the window is moved, the result to be calculated needs to be updated according to the new and/or removed elements in the window. For example, if you need to calculate the sum of elements in a window, when an element is added to the window, this element needs to be added to the sum; when an element is removed from the window, this element needs to be subtracted from the sum.

By constantly moving the window and updating the result, we can get the solution of the problem after traversing the array or string once.

4. Practice of sliding window algorithm

Let us use the following specific examples to gain a deep understanding of how to apply the sliding window algorithm in practical problems.

1. Maximum/minimum subsequence problem in an array: Maximum contiguous subarray sum

Problem description : Given an array of integers nums, find a continuous subarray with the largest sum (the subarray contains at least one element), and return its largest sum.

Java solution :

public int maxSubArray(int[] nums) {
    
    
    int n = nums.length;
    // 初始化当前子数组的和为第一个元素的值,最大和也为第一个元素的值
    int curr_sum = nums[0], max_sum = nums[0];

    // 从第二个元素开始遍历数组
    for(int i = 1; i < n; ++i) {
    
    
        // 更新当前和,取当前元素与(当前和+当前元素)中的最大值
        curr_sum = Math.max(nums[i], curr_sum + nums[i]);
        // 更新最大和,取当前最大和与当前和中的最大值
        max_sum = Math.max(max_sum, curr_sum);
    }
    // 返回最大和
    return max_sum;
}

Code analysis :

In the above code, curr_sumit is used to save the sum of the current sub-array, and max_sumit is used to save the largest sub-array sum. Initialized to the first element.

When we iterate through the array starting from the second element, for each element we have two options, either add it to the current subarray, or start a new subarray (ie the element itself becomes a new subarray). It depends on the size relationship between curr_sum + nums[i]and nums[i], we use Math.max(nums[i], curr_sum + nums[i])to judge, choose the larger one as the new one curr_sum.

At the same time, we also need to update max_sum, that is, the maximum subarray sum. Math.max(max_sum, curr_sum)It is realized by , that is, the larger of max_sumand is selected curr_sumas the new one max_sum.

The final return max_sumis the largest subarray sum.

2. Fixed-length subsequence problem: a non-repeating character substring of length K

Problem Description : Given a string s, find Kthe number of non-repeating substrings of length .

Java solution :

public int numKLenSubstrNoRepeats(String s, int K) {
    
    
    // 计数数组,用于记录字符出现的次数
    int[] count = new int[26];
    int res = 0;
    // 双指针遍历字符串
    for (int i = 0, j = 0; j < s.length(); j++) {
    
    
        // 当前字符出现次数加1,如果这是第一次出现,则K减1
        if (count[s.charAt(j) - 'a']++ == 0) K--;
        // 如果K小于0,说明窗口太大,需要移动左指针缩小窗口
        if (K < 0 && count[s.charAt(i++) - 'a']-- == 1) K++;
        // 如果K等于0,说明找到了一个满足条件的子串,结果加1
        if (K == 0) res++;
    }
    return res;
}

Code analysis :

In this code, we define an countarray to count the number of times each character appears in the sliding window. iAt the same time, two pointers and are defined j, representing the left and right borders of the window respectively.

We slide jthe pointer from left to right (ie traverse the string). If traversed to

The first occurrence of the character, then Kdecrement by one. When Kis less than 0, it means that the window is too large, and characters appear repeatedly, and the left pointer needs to be moved to ishrink the window until it Kis greater than or equal to 0. In the process of moving i, we need to decrease the number of characters leaving the window by one, and if the number of this character becomes 0, then Kincrease by one. Every time when Kis 0, we have found a Knon-repeating character substring of length, resand add one.

3. Counting problems: the sum of subarrays is equal to the number of K

Problem Description : Given an array of integers and an integer k, you need to find kthe number of consecutive subarrays whose sum is .

Java solution :

public int subarraySum(int[] nums, int k) {
    
    
    // 用于保存前缀和及其出现的次数
    Map<Integer, Integer> countMap = new HashMap<>();
    // 初始化前缀和为0的次数为1
    countMap.put(0, 1);

    int sum = 0, count = 0;
    // 遍历数组,计算前缀和
    for (int num : nums) {
    
    
        sum += num;
        // 如果存在一个前缀和等于当前前缀和减去k的值,那么就找到了一个和为k的子数组
        if (countMap.containsKey(sum - k)) {
    
    
            count += countMap.get(sum - k);
        }
        // 将当前前缀和添加到哈希表中,如果已经存在,则次数加1
        countMap.put(sum, countMap.getOrDefault(sum, 0) + 1);
    }
    return count;
}

Code analysis :

In this code, we use a hash table countMapto store the prefix and its occurrence count. Each time we calculate the prefix sum to the current position sum, and then check if it exists in the hash table sum - k. If it exists, then a subarray sum is found k, the result countplus sum - kthe number of occurrences of . Finally, put the current prefix and suminto the hash table and update its occurrence count.

The above is the application of the sliding window algorithm in practical problems. Through these examples, we can see the efficiency and practicability of the sliding window algorithm in dealing with such problems.

5. Comparison of sliding window and other algorithms

Sliding window algorithm is a commonly used optimization strategy, which has similarities with some other algorithms in implementation and use, and also has its unique advantages. Let's compare with some other commonly used algorithms.

1. Comparison with dynamic programming

Dynamic programming is a strategy for solving optimization problems, which decomposes the problem into multiple sub-problems, and then constructs the solution of the original problem based on the solutions of the sub-problems. It saves the solution of each subproblem, avoiding double computation.

The main difference between sliding window algorithms and dynamic programming is that sliding window algorithms do not need to store the solution of each subproblem. Instead, it "slides" a fixed-size window on the original array, reducing the space complexity by optimizing the calculation process. For some specific problems, such as the maximum/minimum consecutive subsequence problem, sliding window algorithms may be more efficient than dynamic programming.

2. Comparison with divide and conquer

Divide and conquer is a common strategy for dealing with complex problems. It decomposes the problem into several smaller, easier-to-handle sub-problems, and then combines the solutions of these sub-problems to obtain the solution of the original problem.

A major difference between sliding window algorithms and divide and conquer is that sliding window algorithms do not require the problem to be broken down. Instead, it finds the solution directly on the original data structure by moving the boundaries of the window, which avoids the complicated process of decomposing the problem and combining the solutions.

3. Comparison with double pointer method

The double pointer method is a strategy for dealing with array or linked list problems that uses two pointers to advance through the structure, usually one faster and one slower, or one before and one after.

The sliding window algorithm can be regarded as an application of the double-pointer method, and the left and right boundaries of the window are two pointers. However, the sliding window algorithm introduces the concept of "window" on this basis, which makes it more intuitive when dealing with certain problems, such as the need to consider the problem of continuous subsequences.

When used, the sliding window algorithm, dynamic programming, divide and conquer method and double pointer method have their own advantages, and the most suitable method needs to be selected according to the specific problem characteristics and data structure. After understanding the basic ideas and advantages and disadvantages of these algorithms, we can choose more flexibly in different problems and scenarios.

6. Summary

Sliding window is an efficient algorithm optimization strategy, which is suitable for solving various scenarios that need to deal with continuous subsequences or subarrays. Its advantage is that by sliding the window on the data structure, it can solve the problem with linear complexity, which greatly improves the efficiency of the algorithm.

The basic steps of a sliding window algorithm include initializing the window position and size, updating the window according to conditions, and saving and updating the result. These steps seem simple, but in practical applications, how to reasonably adjust the position and size of the window, and how to precisely define and update the result often requires some thoughtful and practical experience.

In the practical application of the sliding window algorithm, we discussed in detail the implementation methods for dealing with the maximum/minimum subsequence problem, the fixed-length subsequence problem and the counting problem. In actual programming, these problems often appear in various forms. Understanding and mastering the application of sliding window algorithms can help us solve such problems more efficiently.

In addition, we also compared the sliding window algorithm with other common algorithms, and analyzed their respective advantages and usage scenarios. Sliding window algorithm, dynamic programming, divide and conquer and double pointer method have their own characteristics, and the problems they are suitable for solving are also different. Mastering these tools proficiently and choosing them flexibly according to the actual situation is an essential skill for every programmer.

In the process of learning and using sliding window algorithms, various difficulties and challenges may be encountered. But as long as we deeply understand its principles and practice more, we will be able to overcome difficulties and effectively use the sliding window algorithm to solve problems.

I hope this blog helps you understand and master the sliding window algorithm. If you have any questions or want to discuss issues, please leave a message in the comment area. Let us learn together and make progress together!

Guess you like

Origin blog.csdn.net/weixin_46703995/article/details/131417289