Scala使用foldLeft查找数组重复元素时遇数组越界异常求助
问题分析与修复
1. 数组越界错误原因
你代码里的nums.map(transformValues(nums))是核心错误:
transformValues(nums)会先执行并返回一个数组(比如你的输入数组会返回[1,1,1,2])map方法需要接收一个Int => B的函数,但你把返回的数组直接传给了map,这相当于把原数组的每个元素当成索引去访问这个返回的数组。- 原数组里的元素
5会尝试访问返回数组的第5位,但返回数组长度只有4,直接触发索引越界异常。
2. 逻辑错误
你误以为map(transformValues(nums))会对每个元素执行转换,但实际是把返回数组当成了索引映射函数,完全偏离了你的需求。而且transformValues自身的逻辑也有问题:
nums.tail.contains(nextEl)的判断逻辑错误:它会把只出现一次但存在于nums.tail中的元素也加入结果(比如输入数组的最后一个元素2,nums.tail包含它,但它在整个数组中仅出现一次),导致结果不符合预期。
3. 修复后的代码
要实现“找出数组中所有重复出现的元素的所有实例”,更简洁且高效的写法是先统计元素频率,再过滤出频率大于1的元素:
def findDuplicates(nums: Array[Int]): List[Int] = { // 统计每个元素的出现次数 val elementCounts = nums.groupBy(identity).mapValues(_.length) // 过滤出出现次数大于1的元素,转成List nums.filter(num => elementCounts(num) > 1).toList } val arr = Array(5, 1, 1, 1, 2) println(findDuplicates(arr)) // 输出: List(1, 1, 1)
如果坚持保留你的transformValues思路,需要修正两个点:
- 修正
findDuplicates的调用方式,直接返回transformValues(nums).toList - 修正
transformValues的判断逻辑,改为统计当前元素在整个数组中的出现次数:
def findDuplicates(nums: Array[Int]): List[Int] = { transformValues(nums).toList } def transformValues(nums: Array[Int]): Array[Int] = { nums.foldLeft(Array[Int]())((accumValue, nextEl) => { // 判断当前元素在整个数组中出现次数是否大于1 if (nums.count(_ == nextEl) > 1) accumValue :+ nextEl else accumValue }) } val arr = Array(5, 1, 1, 1, 2) println(findDuplicates(arr)) // 输出: List(1, 1, 1)
不过这种方式的时间复杂度是O(n²),因为每次count都会遍历整个数组,对于大数据量效率较低,更推荐第一种用groupBy的O(n)方案。
内容的提问来源于stack exchange,提问作者Anastasia
相关产品推荐
相关产品推荐

