LeetCode第3题lengthOfLongestSubstring控制台正常但提交报错求助
解决LeetCode最长无重复子串问题时的TypeError错误
问题背景
这是LeetCode第3题(最长无重复字符的子串)的代码问题:我写的代码里,console.log(picked_length)输出完全符合预期,但注释掉return 5;改成返回picked_length时,提交就报错。
我的代码
/** * @param {string} s * @return {number} */ var lengthOfLongestSubstring = function(s) { console.log('input', s); var max_length = s.length; var results = []; var isDupCheck = function(arr){ var s = []; var hasDup = false; arr.forEach(function(el){ if (!s.includes(el)) { s.push(el); } else { hasDup = true; } }) return hasDup; } for (var j = 0; j<max_length; j++) for (var i = 1; i<max_length; i++) { var substr = s.substr(j, i); var isDup = isDupCheck(substr.split('')); if (!isDup) { results.push(substr); } } var length = 0; var picked; console.log("results:", results); results.forEach(function(el){ if (el.length > length) { length = el.length; picked = el; } }); var picked_length = picked.split('').length; console.log(picked_length); // expected output return 5; // 注释这行就会报错 return picked_length; };
报错信息
Line 42 in solution.js var picked_length = picked.split('').length; ^ TypeError: 无法读取undefined的属性'split' Line 42: Char 30 in solution.js (lengthOfLongestSubstring) Line 57: Char 19 in solution.js (Object.<anonymous>) Line 16: Char 8 in runner.js (Object.runner) Line 48: Char 26 in solution.js (Object.<anonymous>) at Module._compile (node:internal/modules/cjs/loader:1101:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) at node:internal/main/run_main_module:17:47
问题原因与修复
核心错误原因
- 边界情况未处理:当输入字符串为空(
s = "")时,results数组是空的,results.forEach不会执行,picked保持初始的undefined状态,调用picked.split('')自然会触发TypeError。 - 循环范围错误:原代码内层循环
i < max_length,导致无法取到长度等于原字符串的子串(比如整个字符串无重复时,不会被加入results)。 - 性能冗余:存储所有符合条件的子串完全没必要,只会浪费内存,直接跟踪最大长度即可。
修正后的代码
/** * @param {string} s * @return {number} */ var lengthOfLongestSubstring = function(s) { const maxLength = s.length; // 空字符串直接返回0 if (maxLength === 0) return 0; let maxResult = 1; // 非空字符串最小长度为1 // 用Set优化重复检查,性能从O(n)提升到O(1) const hasDuplicate = (arr) => { const seen = new Set(); for (const char of arr) { if (seen.has(char)) return true; seen.add(char); } return false; }; for (let j = 0; j < maxLength; j++) { // 内层循环只需要遍历到maxLength - j,避免越界 for (let i = 1; i <= maxLength - j; i++) { const substr = s.substr(j, i); if (!hasDuplicate(substr.split(''))) { maxResult = Math.max(maxResult, i); } else { // 一旦发现重复,更长的子串必然包含该重复字符,直接跳出内层循环 break; } } } return maxResult; };
关键优化点
- 提前处理空字符串的边界情况,避免后续报错
- 用
Set替代数组includes检查重复,大幅提升性能 - 不再存储所有子串,只跟踪最大长度,节省内存
- 内层循环发现重复时直接break,减少不必要的遍历
- 修正循环范围,确保能覆盖所有可能的子串长度
内容的提问来源于stack exchange,提问作者AGamePlayer
相关产品推荐
相关产品推荐

