CodeWars手套配对题:循环内加i++修复计数错误的原理
《Pair of gloves》代码bug原因解释
核心错误逻辑
解题思路是先对原手套数组排序,让同颜色的手套连续排列,再遍历查找相邻同色项计数配对,这个方向本身是正确的,但第一版代码违反了配对的基本规则:已经凑成一对的两只手套,不能再参与后续的配对计算。
错误复现
我们拿最简单的边界样例测试第一版代码:输入为3只同色手套["red", "red", "red"],正确配对数应该是1对(剩余1只单只无法配对),第一版代码的执行流程如下:
- 排序后数组为
["red", "red", "red"],初始i=0 - i=0时,判断
glove[0] == glove[1]成立,向pairs数组推入1个配对,此时计数为1 - 循环自带的自增逻辑生效,i变为1
- i=1时,判断
glove[1] == glove[2]成立,再次向pairs数组推入1个配对,此时计数变为2,结果错误
出现这个问题的原因是:索引1位置的手套,已经和索引0位置的手套凑成一对了,但第一版代码没有跳过这个已使用的手套,反而把它和索引2位置的手套再次凑对,相当于重复使用了同一只手套,导致计数虚高。如果是连续4只同色手套,第一版会算出3对的错误结果,和正确值2对偏差更大。
新增i++的修复原理
当在匹配成功的分支内新增i++后,相当于凑成一对时主动多跳一位:
- 当在索引i位置找到配对(i和i+1为同色),说明这两个位置的手套都已被使用,下一次遍历应该从i+2位置开始
- 循环本身每次迭代结束会自带一次
i++,匹配成功时分支内额外执行一次i++,刚好让索引总共增加2,直接跳过已经配对完成的i+1位置,避免重复使用已配对的手套。
还是拿3只同色手套的样例看修复后的执行流程:
- 初始i=0,匹配到i和i+1同色,推入1个配对,分支内
i++让i变为1 - 循环自带的自增逻辑生效,i变为2
- 此时判断循环条件
i < glove.length -1即2 < 2不成立,循环结束,最终计数为1,结果正确。
附两版实现代码
第一版(存在计数错误)
function numberOfPairs(gloves) { const glove = gloves.slice().sort(); const pairs = []; for (let i = 0; i < glove.length - 1; i++) { if (glove[i] == glove[i+1]) { pairs.push(glove[i]); } } return pairs.length; }
第二版(修复后可通过全量测试)
function numberOfPairs(gloves) { const glove = gloves.slice().sort(); const pairs = []; for (let i = 0; i < glove.length - 1; i++) { if (glove[i] == glove[i+1]) { pairs.push(glove[i]); i++ // 跳过已配对的下一只手套,避免重复计数 } } return pairs.length; }
内容的提问来源于stack exchange,提问作者Mark M.
相关产品推荐
相关产品推荐

