最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何利用栈完成方向字符串的自动对消简化
时间:2026-06-29 09:59:46 编辑:袖梨 来源:一聚教程网
本文详解使用栈结构消除相反方向(如NORTH/SOUTH、EAST/WEST)的算法原理,重点解析stack[stack.length - 1]的安全访问逻辑、空栈边界行为,以及为何不会因读取未定义值导致错误。
本文详解使用栈结构消除相反方向(如north/south、east/west)的算法原理,重点解析`stack[stack.length - 1]`的安全访问逻辑、空栈边界行为,以及为何不会因读取未定义值导致错误。
该函数 dirReduc 的核心思想是:利用栈的“后进先出”特性,实时匹配并抵消相邻的相反方向。例如,['NORTH', 'SOUTH'] 应被完全移除;而 ['NORTH', 'EAST', 'SOUTH'] 中,NORTH 与 SOUTH 不相邻,故不抵消——但本算法通过栈动态维护“尚未被抵消的方向序列”,使非相邻但可间接抵消的方向也能被处理(如 ['NORTH', 'SOUTH', 'SOUTH'] → 先抵消前两个,留下 ['SOUTH'])。
关键点在于对 stack[stack.length - 1] 的访问:
- 当 stack 为空时,stack.length 为 0,因此 stack[stack.length - 1] 等价于 stack[-1] —— JavaScript 中这是合法语法,返回 undefined,而非报错。
- 在条件判断中,undefined === 'NORTH' 等所有比较结果均为 false,因此整个 if 条件不成立,流程自然进入 else 分支,将当前方向 push 入栈。
- 换言之:空栈时的 stack[stack.length - 1] 安全且可控,它保证了首次循环必走 push 路径,从而让栈逐步“建立起来”。
下面是一个带调试注释的增强版实现:
function dirReduc(arr) { const stack = []; for (let direction of arr) { const last = stack[stack.length - 1]; // 可能为 undefined(空栈时) // 只有当栈非空且方向相反时才抵消 const isOpposite = (direction === 'NORTH' && last === 'SOUTH') || (direction === 'SOUTH' && last === 'NORTH') || (direction === 'EAST' && last === 'WEST') || (direction === 'WEST' && last === 'EAST'); if (isOpposite) { stack.pop(); // 抵消:移除栈顶 console.log(`抵消: ${last} ←→ ${direction}, 栈变为 [${stack.join(', ')}]`); } else { stack.push(direction); // 累积:入栈 console.log(`入栈: ${direction}, 栈变为 [${stack.join(', ')}]`); } } return stack;}// 示例调用console.log(dirReduc(['NORTH', 'SOUTH', 'EAST', 'WEST'])); // → []console.log(dirReduc(['NORTH', 'SOUTH', 'SOUTH', 'EAST', 'WEST', 'WEST'])); // → ['SOUTH', 'WEST']
⚠️ 注意事项:
- 该算法仅处理直接相反的两两方向,不支持斜向(如 'NORTHEAST')或自定义映射;
- 时间复杂度为 O(n),空间复杂度最坏 O(n)(无任何抵消时);
- 若输入含非法方向(如 'UP'),它会被无条件入栈——建议在生产环境增加校验;
- stack[stack.length - 1] 是惯用写法,等价于 stack.at(-1)(ES2022+),后者语义更清晰,但兼容性略低。
总结:栈在此处扮演“待决方向缓冲区”的角色;stack[stack.length - 1] 的巧妙之处,在于它天然兼容空栈场景,无需额外 if (stack.length > 0) 判断——这正是函数简洁而健壮的关键设计。