From 012ee576e903cd79421357957b49474bdcd38dfd Mon Sep 17 00:00:00 2001 From: Subhamstar Date: Sun, 23 Nov 2025 22:45:37 +0530 Subject: [PATCH] Add Longest Substring with K Distinct Characters sliding window algorithm with tests --- .../strings/LongestSubstringKDistinct.java | 42 +++++++++++++++++++ .../LongestSubstringKDistinctTest.java | 26 ++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/main/java/com/thealgorithms/strings/LongestSubstringKDistinct.java create mode 100644 src/test/java/com/thealgorithms/strings/LongestSubstringKDistinctTest.java diff --git a/src/main/java/com/thealgorithms/strings/LongestSubstringKDistinct.java b/src/main/java/com/thealgorithms/strings/LongestSubstringKDistinct.java new file mode 100644 index 000000000000..407533cf0ffa --- /dev/null +++ b/src/main/java/com/thealgorithms/strings/LongestSubstringKDistinct.java @@ -0,0 +1,42 @@ +package com.thealgorithms.strings; + +import java.util.HashMap; + +public class LongestSubstringKDistinct { + + /** + * Returns the length of the longest substring that contains + * at most k distinct characters. + * + * Sliding Window + HashMap + * Time Complexity: O(n) + * Space Complexity: O(k) + */ + public static int longestSubstringKDistinct(String s, int k) { + if (k == 0 || s == null || s.isEmpty()) { + return 0; + } + + int left = 0, maxLen = 0; + HashMap map = new HashMap<>(); + + for (int right = 0; right < s.length(); right++) { + char ch = s.charAt(right); + map.put(ch, map.getOrDefault(ch, 0) + 1); + + while (map.size() > k) { + char leftChar = s.charAt(left); + map.put(leftChar, map.get(leftChar) - 1); + + if (map.get(leftChar) == 0) { + map.remove(leftChar); + } + left++; + } + + maxLen = Math.max(maxLen, right - left + 1); + } + + return maxLen; + } +} diff --git a/src/test/java/com/thealgorithms/strings/LongestSubstringKDistinctTest.java b/src/test/java/com/thealgorithms/strings/LongestSubstringKDistinctTest.java new file mode 100644 index 000000000000..5ce204e907f7 --- /dev/null +++ b/src/test/java/com/thealgorithms/strings/LongestSubstringKDistinctTest.java @@ -0,0 +1,26 @@ +package com.thealgorithms.strings; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class LongestSubstringKDistinctTest { + + @Test + void testBasic() { + assertEquals(3, LongestSubstringKDistinct.longestSubstringKDistinct("eceba", 2)); + assertEquals(2, LongestSubstringKDistinct.longestSubstringKDistinct("aa", 1)); + } + + @Test + void testEdgeCases() { + assertEquals(0, LongestSubstringKDistinct.longestSubstringKDistinct("", 2)); + assertEquals(0, LongestSubstringKDistinct.longestSubstringKDistinct("abc", 0)); + } + + @Test + void testLarge() { + assertEquals(4, LongestSubstringKDistinct.longestSubstringKDistinct("aabbcc", 2)); + assertEquals(6, LongestSubstringKDistinct.longestSubstringKDistinct("abcabcbb", 3)); + } +}