Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Tag Validator

Updated
4 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "591" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.

Problem Statement

Given a string representing a code snippet, implement a tag validator to parse the code and return whether it is valid. A code snippet is valid if all the following rules hold: The code must be wrapped in a valid closed tag. Otherwise, the code is invalid. A closed tag (not necessarily valid) has exactly the following format : TAG_CONTENT. Among them, is the start tag, and is the end tag. The TAG_NAME in start and end tags should be the same. A closed tag is valid if and only if the TAG_NAME and TAG_CONTENT are valid. A valid TAG_NAME only contain upper-case letters, and has length in range [1,9]. Otherwise, the TAG_NAME is invalid. A valid TAG_CONTENT may contain other valid closed tags, cdata and any characters (see note1) EXCEPT unmatched <, unmatched start and end tag, and unmatched or closed tags with invalid TAG_NAME. Otherwise, the TAG_CONTENT is invalid. A start tag is unmatched if no end tag exists with the same TAG_NAME, and vice versa. However, you also need to consider the issue of unbalanced when tags are nested. A < is unmatched if you cannot find a subsequent >. And when you find a < or </, all the subsequent characters until the next > should be parsed as TAG_NAME (not necessarily valid). The cdata has the following format : <![CDATA[CDATA_CONTENT]]>. The range of CDATA_CONTENT is defined as the characters between <![CDATA[ and the first subsequent ]]>. CDATA_CONTENT may contain any characters. The function of cdata is to forbid the validator to parse CDATA_CONTENT, so even it has some characters that can be parsed as tag (no matter valid or invalid), you should treat it as regular characters. Example 1: Input: code = "

This is the first line <![CDATA[
]]>
" Output: true Explanation: The code is wrapped in a closed tag :
and
. The TAG_NAME is valid, the TAG_CONTENT consists of some characters and cdata. Although CDATA_CONTENT has an unmatched start tag with invalid TAG_NAME, it should be considered as plain text, not parsed as a tag. So TAG_CONTENT is valid, and then the code is valid. Thus return true. Example 2: Input: code = "
>> ![cdata[]] <![CDATA[
]>]]>]]>>]
" Output: true Explanation: We first separate the code into : start_tag|tag_content|end_tag. start_tag -> "
" end_tag -> "
" tag_content could also be separated into : text1|cdata|text2. text1 -> ">> ![cdata[]] " cdata -> "<![CDATA[
]>]]>", where the CDATA_CONTENT is "
]>" text2 -> "]]>>]" The reason why start_tag is NOT "
>>" is because of the rule 6. The reason why cdata is NOT "<![CDATA[

Explanation

  • High-Level Approach: The solution uses a stack to keep track of open tags. It iterates through the code string, handling start tags, end tags, and CDATA sections. It checks for tag name validity, balanced tags, and invalid content characters. The stack ensures proper nesting.
    • Complexity:
  • Runtime Complexity: O(n), where n is the length of the code string.
  • Storage Complexity: O(n), where n is the length of the code string (in worst-case scenarios where there are many nested tags).
    • Code:

Code

    import re

def isValid(code: str) -> bool:
    """
    Validates a code snippet based on the defined rules.
    """
    stack = []
    i = 0
    n = len(code)

    def is_valid_tag_name(tag_name: str) -> bool:
        return bool(re.match(r"^[A-Z]{1,9}$", tag_name))

    while i < n:
        if code[i:i + 9] == "<![CDATA[":
            i += 9
            j = i
            while j < n and code[j:j + 3] != "]]>":
                j += 1
            if j == n:
                return False
            i = j + 3
        elif code[i:i + 2] == "</":
            i += 2
            j = i
            while j < n and code[j] != ">":
                j += 1
            if j == n:
                return False
            tag_name = code[i:j]
            if not is_valid_tag_name(tag_name):
                return False
            if not stack or stack[-1] != tag_name:
                return False
            stack.pop()
            i = j + 1
        elif code[i] == "<":
            i += 1
            j = i
            while j < n and code[j] != ">":
                j += 1
            if j == n:
                return False
            tag_name = code[i:j]
            if not is_valid_tag_name(tag_name):
                return False
            stack.append(tag_name)
            i = j + 1
        else:
            i += 1
        if not stack and i < n:
            return False

    return not stack

More from this blog

C

Chatmagic blog

2894 posts