From a00458c130adeb684e1a4ebc42fd8aaea5a15618 Mon Sep 17 00:00:00 2001 From: jaimin45-art Date: Fri, 17 Oct 2025 14:26:32 +0530 Subject: [PATCH] Added MinimumWindowSubstring algorithm and test (Sliding Window) --- .../strings/MinimumWindowSubstring.java | 64 +++++++++++++++++++ .../strings/MinimumWindowSubstringTest.java | 27 ++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/main/java/com/thealgorithms/strings/MinimumWindowSubstring.java create mode 100644 src/test/java/com/thealgorithms/strings/MinimumWindowSubstringTest.java diff --git a/src/main/java/com/thealgorithms/strings/MinimumWindowSubstring.java b/src/main/java/com/thealgorithms/strings/MinimumWindowSubstring.java new file mode 100644 index 000000000000..b9ba8dc12e5b --- /dev/null +++ b/src/main/java/com/thealgorithms/strings/MinimumWindowSubstring.java @@ -0,0 +1,64 @@ +package com.thealgorithms.strings; + +/** + * Minimum Window Substring + * + * Given two strings s and t, return the minimum window substring of s such that + * every character in t (including duplicates) is included in the window. + * + * If there is no such substring, return an empty string "". + * + * Approach: Sliding Window + Frequency Table. + * + * Time complexity: O(n + m) + * Space complexity: O(1) for ASCII characters. + * + * Reference: https://en.wikipedia.org/wiki/Minimum_window_substring + */ +public final class MinimumWindowSubstring { + + private MinimumWindowSubstring() { + throw new UnsupportedOperationException("Utility class"); + } + + public static String minWindow(String s, String t) { + if (s == null || t == null || s.length() < t.length() || t.isEmpty()) { + return ""; + } + + int[] need = new int[256]; + for (char c : t.toCharArray()) { + need[c]++; + } + + int required = 0; + for (int i = 0; i < 256; i++) { + if (need[i] > 0) required++; + } + + int l = 0, r = 0, formed = 0; + int[] window = new int[256]; + int minLen = Integer.MAX_VALUE, minLeft = 0; + + while (r < s.length()) { + char c = s.charAt(r); + window[c]++; + if (need[c] > 0 && window[c] == need[c]) formed++; + + while (l <= r && formed == required) { + if (r - l + 1 < minLen) { + minLen = r - l + 1; + minLeft = l; + } + + char d = s.charAt(l); + window[d]--; + if (need[d] > 0 && window[d] < need[d]) formed--; + l++; + } + r++; + } + + return minLen == Integer.MAX_VALUE ? "" : s.substring(minLeft, minLeft + minLen); + } +} diff --git a/src/test/java/com/thealgorithms/strings/MinimumWindowSubstringTest.java b/src/test/java/com/thealgorithms/strings/MinimumWindowSubstringTest.java new file mode 100644 index 000000000000..6ab95177f6f1 --- /dev/null +++ b/src/test/java/com/thealgorithms/strings/MinimumWindowSubstringTest.java @@ -0,0 +1,27 @@ +package com.thealgorithms.strings; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +public class MinimumWindowSubstringTest { + + @Test + public void testExample1() { + assertEquals("BANC", MinimumWindowSubstring.minWindow("ADOBECODEBANC", "ABC")); + } + + @Test + public void testExample2() { + assertEquals("", MinimumWindowSubstring.minWindow("A", "AA")); + } + + @Test + public void testExample3() { + assertEquals("a", MinimumWindowSubstring.minWindow("a", "a")); + } + + @Test + public void testExample4() { + assertEquals("t stri", MinimumWindowSubstring.minWindow("test string", "tist")); + } +}