我来为你详细解析 LeetCode 591. 标签验证器这道题的解法。题目理解这道题要求验证一段代码是否是有效的标签代码规则比较复杂涉及开始标签TAG_NAME大写字母1-9个字符结束标签/TAG_NAME与开始标签匹配CDATA![CDATA[...]]内容不解析嵌套标签标签可以嵌套但必须正确闭合核心思路使用栈来处理标签的匹配同时需要处理三种情况开始标签TAG→ 入栈结束标签/TAG→ 出栈并匹配CDATA![CDATA[...]]→ 跳过不处理完整代码实现publicbooleanisValid(Stringcode){StackStringstacknewStack();intncode.length();inti0;while(in){if(code.charAt(i)){// 检查是否是结束标签if(i1ncode.charAt(i1)/){// 结束标签 /TAG_NAMEintjcode.indexOf(,i);if(j0)returnfalse;// 没有闭合StringtagNamecode.substring(i2,j);// 验证标签名if(!isValidTagName(tagName))returnfalse;// 栈不能为空且必须匹配栈顶if(stack.isEmpty()||!stack.pop().equals(tagName))returnfalse;ij1;// 如果栈为空但不是字符串末尾说明后面还有内容在根标签外if(stack.isEmpty()i!n)returnfalse;}// 检查是否是CDATAelseif(i8ncode.substring(i,i9).equals(![CDATA[)){// CDATA 必须出现在某个标签内if(stack.isEmpty())returnfalse;intjcode.indexOf(]],i9);if(j0)returnfalse;// CDATA未闭合ij3;// 跳过 ]]}// 开始标签 TAG_NAMEelse{intjcode.indexOf(,i);if(j0)returnfalse;// 没有闭合StringtagNamecode.substring(i1,j);// 验证标签名if(!isValidTagName(tagName))returnfalse;// 开始标签不能出现在已有内容之后除非在标签内if(stack.isEmpty()i!0)returnfalse;stack.push(tagName);ij1;}}else{// 普通字符必须在某个标签内if(stack.isEmpty())returnfalse;i;}}// 最后栈必须为空所有标签都闭合returnstack.isEmpty();}// 验证标签名大写字母1-9个字符privatebooleanisValidTagName(Stringname){if(name.length()1||name.length()9)returnfalse;for(charc:name.toCharArray()){if(cA||cZ)returnfalse;}returntrue;}关键规则总结规则 说明根标签 整个代码必须被包裹在一个根标签内标签名 1-9个大写字母匹配 开始标签和结束标签必须匹配栈CDATA 内容原样输出不解析其中的标签内容位置 普通字符必须在某个标签内不能在根标签外复杂度分析时间复杂度O(n)只需遍历字符串一次空间复杂度O(n)最坏情况下栈的深度为 n/3易错点提醒根标签判断栈为空时遇到字符非是非法的CDATA位置CDATA必须在某个标签内部不能在最外层结束后的内容根标签闭合后不能再有内容标签名长度严格限制 1-9 个字符需要我针对某个具体测试用例或边界情况再详细解释吗
Kimi LeetCode 591.标签验证器 public boolean isValid(String code)
我来为你详细解析 LeetCode 591. 标签验证器这道题的解法。题目理解这道题要求验证一段代码是否是有效的标签代码规则比较复杂涉及开始标签TAG_NAME大写字母1-9个字符结束标签/TAG_NAME与开始标签匹配CDATA![CDATA[...]]内容不解析嵌套标签标签可以嵌套但必须正确闭合核心思路使用栈来处理标签的匹配同时需要处理三种情况开始标签TAG→ 入栈结束标签/TAG→ 出栈并匹配CDATA![CDATA[...]]→ 跳过不处理完整代码实现publicbooleanisValid(Stringcode){StackStringstacknewStack();intncode.length();inti0;while(in){if(code.charAt(i)){// 检查是否是结束标签if(i1ncode.charAt(i1)/){// 结束标签 /TAG_NAMEintjcode.indexOf(,i);if(j0)returnfalse;// 没有闭合StringtagNamecode.substring(i2,j);// 验证标签名if(!isValidTagName(tagName))returnfalse;// 栈不能为空且必须匹配栈顶if(stack.isEmpty()||!stack.pop().equals(tagName))returnfalse;ij1;// 如果栈为空但不是字符串末尾说明后面还有内容在根标签外if(stack.isEmpty()i!n)returnfalse;}// 检查是否是CDATAelseif(i8ncode.substring(i,i9).equals(![CDATA[)){// CDATA 必须出现在某个标签内if(stack.isEmpty())returnfalse;intjcode.indexOf(]],i9);if(j0)returnfalse;// CDATA未闭合ij3;// 跳过 ]]}// 开始标签 TAG_NAMEelse{intjcode.indexOf(,i);if(j0)returnfalse;// 没有闭合StringtagNamecode.substring(i1,j);// 验证标签名if(!isValidTagName(tagName))returnfalse;// 开始标签不能出现在已有内容之后除非在标签内if(stack.isEmpty()i!0)returnfalse;stack.push(tagName);ij1;}}else{// 普通字符必须在某个标签内if(stack.isEmpty())returnfalse;i;}}// 最后栈必须为空所有标签都闭合returnstack.isEmpty();}// 验证标签名大写字母1-9个字符privatebooleanisValidTagName(Stringname){if(name.length()1||name.length()9)returnfalse;for(charc:name.toCharArray()){if(cA||cZ)returnfalse;}returntrue;}关键规则总结规则 说明根标签 整个代码必须被包裹在一个根标签内标签名 1-9个大写字母匹配 开始标签和结束标签必须匹配栈CDATA 内容原样输出不解析其中的标签内容位置 普通字符必须在某个标签内不能在根标签外复杂度分析时间复杂度O(n)只需遍历字符串一次空间复杂度O(n)最坏情况下栈的深度为 n/3易错点提醒根标签判断栈为空时遇到字符非是非法的CDATA位置CDATA必须在某个标签内部不能在最外层结束后的内容根标签闭合后不能再有内容标签名长度严格限制 1-9 个字符需要我针对某个具体测试用例或边界情况再详细解释吗