Permutation in String


Permutation in String – LeetCode #567


Problem Statement

You are given two strings s1 and s2.
Return true if s2 contains a permutation of s1, else return false.

In other words, check if any substring of s2 has the same character frequency as s1.


Examples


Constraints


Intuition

We need to check whether any substring of s2 (of length equal to s1) is a permutation of s1.

This is a Fixed-Size Sliding Window + Frequency Array Matching problem:

Instead of generating permutations explicitly (which is factorial time), we compare the frequency signatures of sliding windows.


Approach

  1. If s1.length() > s2.length(), return false.

  2. Initialize two frequency arrays:

    • s1Count for s1

    • s2Count for the current window in s2

  3. Fill both arrays for the first window of size s1.length().

  4. For each new character entering the window:

    • Compare s1Count with s2Count:

      • If they match, return true
    • Slide the window:

      • Decrement the count of the character that’s moving out

      • Increment the count of the character that’s coming in

  5. Finally, check the last window (after the loop ends).


Java Code

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        if (s1.length() > s2.length()) return false;

        int[] s1Count = new int[26];
        int[] s2Count = new int[26];

        // Step 1: Initialize both frequency arrays
        for (int i = 0; i < s1.length(); i++) {
            s1Count[s1.charAt(i) - 'a']++;
            s2Count[s2.charAt(i) - 'a']++;
        }

        // Step 2: Slide the window
        for (int i = 0; i < s2.length() - s1.length(); i++) {
            if (matches(s1Count, s2Count)) return true;

            // Slide: remove leftmost, add rightmost
            s2Count[s2.charAt(i) - 'a']--;
            s2Count[s2.charAt(i + s1.length()) - 'a']++;
        }

        // Final check for last window
        return matches(s1Count, s2Count);
    }

    // Utility to compare two frequency arrays
    private boolean matches(int[] s1Count, int[] s2Count) {
        for (int i = 0; i < 26; i++) {
            if (s1Count[i] != s2Count[i]) return false;
        }
        return true;
    }
}

Time and Space Complexity


Dry Run

Input:

s1 = "ab", s2 = "eidbaooo"

Steps:


Conclusion

This is a Fixed-Size Sliding Window + Hash Lookup (Frequency Arrays) problem.

Key insights:

This pattern is commonly reused in: