
LeetCode 1807: Evaluate the Bracket Pairs of a String – Java Solution & Explanation
IntroductionLeetCode 1807, Evaluate the Bracket Pairs of a String, is a string-processing problem that combines two common techniques:Using a HashMap for fast key-value lookupTraversing a string while keeping track of whether the current characters belong to a bracket pairThe string contains ordinary characters as well as bracketed keys such as:(name)(age)(city)A separate knowledge list provides the value associated with each known key.For every bracket pair:If the key exists in knowledge, replace the entire pair with its value.If the key is not present, replace the entire pair with ?.For example:s = "(name)is(age)yearsold"with:knowledge = [ ["name", "bob"], ["age", "two"]]becomes:bobistwoyearsoldThe main challenge is identifying exactly which characters belong to a bracketed key while keeping the characters outside brackets unchanged.Question LinkLeetCode 1807 – Evaluate the Bracket Pairs of a StringUnderstanding the ProblemConsider:s = "(name)is(age)yearsold"The bracket pairs are:(name)(age)The text outside the brackets is:isyearsoldSuppose:name → bobage → twoThen the transformation is:(name) → bob(age) → twoSo the final result becomes:bobistwoyearsoldThe characters outside brackets should not be interpreted as keys.For example:s = "(a)(a)aaa"with:a → yesproduces:yesyesaaaThe final aaa remains unchanged because those characters are not inside brackets.ApproachThe solution can be divided into two parts.Store the Knowledge in a HashMapThe knowledge array contains pairs such as:["name", "bob"]["age", "two"]These pairs are stored in a HashMap:HashMap<String, String> mp = new HashMap<>();for(int i = 0; i < knowledge.size(); i++){ mp.put( knowledge.get(i).get(0), knowledge.get(i).get(1) );}This gives direct access to a value using its key.For example:mp.get("name")returns:bobAnd:mp.containsKey("unknown")can be used to determine whether a key exists.Because each key appears at most once in knowledge, there is no need to handle duplicate key definitions.Detecting a Bracketed KeyThe solution uses a boolean variable:boolean bo = false;This represents whether the current position is inside a bracket pair.When the character immediately before the current character is '(':if(i > 0 && s.charAt(i - 1) == '('){ key = ""; bo = true;}the solution starts collecting a new key.For example:(name) ^Once n is reached, the previous character is '(', so the solution begins collecting:nnanamnameWhen ')' is encountered:if(s.charAt(i) == ')'){ bo = false;}the key is complete.The solution can then look it up in the map.Replacing the KeyWhen the closing bracket is found, the code checks whether the collected key exists:if(mp.containsKey(key)){ an += mp.get(key); key = "";}else{ an += "?"; key = "";}If the key is known:(name) → bobIf the key is unknown:(address) → ?This directly follows the problem statement.Keeping Characters Outside BracketsCharacters that are not part of a bracketed key are added directly to the result:if(!bo && (s.charAt(i) != ')' && s.charAt(i) != '(')){ an += s.charAt(i);}This is important because ordinary characters must remain unchanged.For:hi(name)the characters:hiare outside the brackets and are therefore copied directly.The key:nameis evaluated separately.Java SolutionHere is the submitted solution with comments explaining the important parts:class Solution { public String evaluate(String s, List<List<String>> knowledge) { // Store key -> value mappings HashMap<String, String> mp = new HashMap<>(); for(int i = 0; i < knowledge.size(); i++){ mp.put( knowledge.get(i).get(0), knowledge.get(i).get(1) ); } String key = ""; // true when we are currently reading a key boolean bo = false; String an = ""; for(int i = 0; i < s.length(); i++){ // The character after '(' starts a new key if(i > 0 && s.charAt(i - 1) == '('){ key = ""; bo = true; } // ')' means the current key is complete if(s.charAt(i) == ')'){ bo = false; } // Characters outside brackets are copied directly if(!bo && s.charAt(i) != ')' && s.charAt(i) != '('){ an += s.charAt(i); } // Characters inside brackets are collected as the key if(bo){ key += s.charAt(i); } // Evaluate the completed key if(key.length() > 0 && s.charAt(i) == ')'){ if(mp.containsKey(key)){ an += mp.get(key); key = ""; } else{ an += "?"; key = ""; } } } return an; }}Dry RunConsider:s = "(name)is(age)"and:knowledge = [ ["name", "bob"], ["age", "two"]]Initially:an = ""Reading (name)The scanner encounters '('.The next characters are collected as the key:nnanamnameWhen ')' is reached:key = "name"The map contains "name":name → bobSo:an = "bob"Reading isThese characters are outside brackets:isThey are copied directly:an = "bobis"Reading (age)The key is collected:aagageAt the closing bracket:key = "age"The map contains:age → twoSo:an = "bobistwo"The final result is:bobistwoHandling an Unknown KeyConsider:s = "hi(name)"with:knowledge = [["a", "b"]]The map contains only:a → bWhen the scanner reaches:(name)the collected key is:nameBut:mp.containsKey("name")is false.Therefore the entire bracket pair is replaced with:?The result becomes:hi?This is an important part of the problem because unknown keys should not remain in the output.Why a HashMap Works WellThe knowledge list can contain up to 10^5 entries.Searching through the entire list for every bracket pair would be unnecessarily expensive.Instead, the solution converts it into:key → valueusing a HashMap.Then a lookup is expected O(1).This makes the solution efficient even when the knowledge list is large.A Small Implementation ImprovementThe submitted solution uses:String an = "";and repeatedly performs:an += ...Java String objects are immutable, so repeatedly concatenating strings can create many intermediate objects.A StringBuilder is more appropriate when constructing a result character by character.The same approach can therefore be written as:class Solution { public String evaluate(String s, List<List<String>> knowledge) { HashMap<String, String> mp = new HashMap<>(); for(List<String> pair : knowledge){ mp.put(pair.get(0), pair.get(1)); } StringBuilder ans = new StringBuilder(); StringBuilder key = new StringBuilder(); boolean inside = false; for(int i = 0; i < s.length(); i++){ char ch = s.charAt(i); if(ch == '('){ inside = true; key.setLength(0); } else if(ch == ')'){ inside = false; String k = key.toString(); if(mp.containsKey(k)){ ans.append(mp.get(k)); } else{ ans.append('?'); } } else if(inside){ key.append(ch); } else{ ans.append(ch); } } return ans.toString(); }}This version expresses the parsing states more directly:'(' → start keyinside brackets → collect key')' → evaluate keyoutside brackets → copy characterComplexity AnalysisLet:n = length of sk = number of entries in knowledgeBuilding the HashMap requires:Time: O(k)The string is scanned once:Time: O(n)Therefore, the overall expected complexity is:Time Complexity: O(n + k)The HashMap stores all known keys and values.Space Complexity: O(k + n)The O(n) component accounts for the output and temporary string-building structures.Interview TipThis problem is a good example of a state-based string traversal.Instead of trying to manipulate the entire string repeatedly, scan it once and maintain a small amount of state:Outside brackets ↓ '(' ↓Inside bracket → collect key ↓ ')' ↓Look up key ↓Append value / '?' ↓Outside bracketsWhen a string contains delimiters such as:(...)[...]{...}a similar state-based approach can often simplify the implementation.The second important pattern is recognizing when a HashMap is appropriate: whenever many lookups need to be performed using a unique key.ConclusionLeetCode 1807 is primarily a string parsing + HashMap lookup problem.The solution first converts the knowledge list into a key-value map. It then scans the string and distinguishes between characters inside and outside brackets.For every bracketed key:known key → corresponding valueunknown key → ?The important implementation ideas are:Use a HashMap for fast key lookup.Track whether the scanner is inside a bracket pair.Collect characters between '(' and ')'.Preserve characters outside brackets.Return the first available result after processing the complete string.The submitted approach follows this logic correctly. For production-quality Java code, StringBuilder is preferable to repeated String concatenation when constructing the result.























