Swift实现sockMerchant数组重复元素配对计数功能运行异常排查
代码问题分析
- 提前终止逻辑错误:
return numberOfPairs被放在for循环内部,只要当前遍历到的元素没有可配对的重复项(首次和末次索引相同),就会直接终止函数返回结果,不会遍历后续元素。比如第二个测试用例遍历到元素2时,检测到没有重复直接返回,自然无法得到正确结果。 - 元素删除顺序错误:你先删除索引更小的
indexOfFirstElement,再删除索引更大的indexOfLastElement。删除第一个元素后,数组整体长度减1,所有索引大于indexOfFirstElement的元素都会前移一位,原本的indexOfLastElement已经失效,此时再删除会导致索引越界或者删错元素。正确的删除顺序应该是先删索引更大的,再删索引更小的,避免小索引的删除操作影响大索引的有效性。 - 遍历范围固定问题:初始化for循环时用的
0..<array.count是取循环执行前的数组长度计算的固定值,后续你不断删除元素导致数组长度变小,循环还是会遍历到超出当前数组长度的索引,触发越界崩溃。
修复后的原逻辑代码
func sockMerchant(n: Int, ar: [Int]) -> Int { var array = ar var numberOfPairs = 0 var i = 0 // 用while循环动态判断数组长度,替代固定范围的for循环 while i < array.count { let element = array[i] guard let indexOfFirstElement = array.firstIndex(of: element), let indexOfLastElement = array.lastIndex(of: element), indexOfFirstElement != indexOfLastElement else { // 当前元素无配对,遍历下一个 i += 1 continue } numberOfPairs += 1 // 先删大索引,再删小索引,避免索引失效 array.remove(at: indexOfLastElement) array.remove(at: indexOfFirstElement) } return numberOfPairs }
更优实现方案(时间复杂度O(n))
不用修改数组,直接用哈希表统计每个元素的出现频率,每个元素的配对数等于出现次数除以2取整,累加所有元素的配对数即可,逻辑更简单性能更高:
func sockMerchant(n: Int, ar: [Int]) -> Int { var countDict = [Int: Int]() ar.forEach { countDict[$0, default: 0] += 1 } return countDict.values.reduce(0) { $0 + $1 / 2 } }
内容的提问来源于stack exchange,提问作者Artun
相关产品推荐
相关产品推荐

