1+ package com .freetymekiyan .algorithms .level .hard ;
2+
3+ import java .util .Collections ;
4+ import java .util .HashMap ;
5+ import java .util .LinkedHashMap ;
6+ import java .util .Map ;
7+
8+ /**
9+ * 340. Longest Substring with At Most K Distinct Characters
10+ * <p>
11+ * Given a string, find the length of the longest substring T that contains at most k distinct characters.
12+ * <p>
13+ * Example 1:
14+ * <p>
15+ * Input: s = "eceba", k = 2
16+ * Output: 3
17+ * Explanation: T is "ece" which its length is 3.
18+ * Example 2:
19+ * <p>
20+ * Input: s = "aa", k = 1
21+ * Output: 2
22+ * Explanation: T is "aa" which its length is 2.
23+ * <p>
24+ * Companies: Facebook, Amazon, Google, Bloomberg, AppDynamics, Coupang
25+ * <p>
26+ * Related Topics: Hash Table, String, Sliding Window
27+ * <p>
28+ * Similar Questions: (M) Longest Substring Without Repeating Characters, (H) Longest Substring with At Most Two
29+ * Distinct Characters, (M) Longest Repeating Character Replacement, (H) Subarrays with K Different Integers, (M) Max
30+ * Consecutive Ones III
31+ */
32+ public class LongestSubstringWithAtMostKDistinctCharacters {
33+
34+ public int lengthOfLongestSubstringKDistinct (String s , int k ) {
35+ int n = s .length ();
36+ if (n * k == 0 ) return 0 ;
37+
38+ // sliding window left and right pointers
39+ int left = 0 ;
40+ int right = 0 ;
41+ // hashmap character -> its rightmost position
42+ // in the sliding window
43+ LinkedHashMap <Character , Integer > hashmap = new LinkedHashMap <>(k + 1 );
44+
45+ int maxLength = 1 ;
46+
47+ while (right < n ) {
48+ Character character = s .charAt (right );
49+ // if character is already in the hashmap -
50+ // delete it, so that after insert it becomes
51+ // the rightmost element in the hashmap
52+ if (hashmap .containsKey (character ))
53+ hashmap .remove (character );
54+ hashmap .put (character , right ++);
55+
56+ // slidewindow contains k + 1 characters
57+ if (hashmap .size () == k + 1 ) {
58+ // delete the leftmost character
59+ Map .Entry <Character , Integer > leftmost = hashmap .entrySet ().iterator ().next ();
60+ hashmap .remove (leftmost .getKey ());
61+ // move left pointer of the slidewindow
62+ left = leftmost .getValue () + 1 ;
63+ }
64+
65+ maxLength = Math .max (maxLength , right - left );
66+ }
67+ return maxLength ;
68+ }
69+
70+ public int lengthOfLongestSubstringKDistinct2 (String s , int k ) {
71+ int n = s .length ();
72+ if (n * k == 0 ) return 0 ;
73+
74+ // sliding window left and right pointers
75+ int left = 0 ;
76+ int right = 0 ;
77+ // hashmap character -> its rightmost position
78+ // in the sliding window
79+ Map <Character , Integer > hashmap = new HashMap <Character , Integer >();
80+
81+ int maxLength = 1 ;
82+
83+ while (right < n ) {
84+ // add new character and move right pointer
85+ hashmap .put (s .charAt (right ), right ++);
86+
87+ // slidewindow contains 3 characters
88+ if (hashmap .size () == k + 1 ) {
89+ // delete the leftmost character
90+ int del_idx = Collections .min (hashmap .values ());
91+ hashmap .remove (s .charAt (del_idx ));
92+ // move left pointer of the slidewindow
93+ left = del_idx + 1 ;
94+ }
95+
96+ maxLength = Math .max (maxLength , right - left );
97+ }
98+ return maxLength ;
99+ }
100+ }
0 commit comments