如何使用reduce重写求解数组最小绝对差的嵌套循环代码?
如何使用reduce重写求解数组最小绝对差的嵌套循环代码?
嘿,我来帮你看看怎么用reduce()重写这段代码!首先得提一句,你原来的双重循环有个小细节可以优化:它会重复计算成对的差值(比如i=0,j=1和i=1,j=0算的是同一个绝对值差),而且初始把res设为0也有点小隐患——虽然逻辑上能跑,但用Infinity初始化最小差值会更严谨,毕竟一开始我们还不知道任何有效差值。
先给你一个用reduce()结合内层for循环的版本,这个写法既保留了函数式风格,又避免了重复计算,效率比你原来的循环高了一倍:
function minimumAbsoluteDifference(arr: number[]): number { // 处理边界情况:数组元素不足2个时直接返回0 if (arr.length < 2) return 0; // 用reduce跟踪当前最小差值,初始值设为Infinity(比任何可能的差值都大) return arr.reduce((minDiff, current, index, array) => { // 只遍历当前元素之后的元素,避免重复计算成对差值 for (let j = index + 1; j < array.length; j++) { const diff = Math.abs(current - array[j]); // 如果当前差值更小,就更新最小差值 if (diff < minDiff) { minDiff = diff; // 提前终止:找到0就直接返回,不可能有更小的差值了 if (minDiff === 0) return minDiff; } } return minDiff; }, Infinity); }
如果你想要完全摆脱for循环,用纯reduce()的写法,也可以用双层reduce实现,不过可读性会稍差一点,而且因为每次都要切割子数组,性能会略逊于上面的版本:
function minimumAbsoluteDifference(arr: number[]): number { if (arr.length < 2) return 0; return arr.reduce((outerMin, current, outerIndex, array) => { // 切割出当前元素之后的子数组,用内层reduce找当前元素和后续元素的最小差 const innerMin = array.slice(outerIndex + 1).reduce((innerMin, next) => { const diff = Math.abs(current - next); return diff < innerMin ? diff : innerMin; }, Infinity); // 比较外层当前最小差和内层计算出的最小差,取更小的那个 return innerMin < outerMin ? innerMin : outerMin; }, Infinity); }
另外想多提一句,如果你真的追求性能,其实先排序数组再用reduce比较相邻元素的方法才是最优解,时间复杂度从原来的O(n²)降到O(n log n),数组越大提升越明显:
function minimumAbsoluteDifference(arr: number[]): number { if (arr.length < 2) return 0; // 先排序数组(注意要复制原数组,避免修改原数组) const sortedArr = [...arr].sort((a, b) => a - b); // 遍历排序后的数组,只比较相邻元素的差值(排序后最小绝对差一定在相邻元素间) return sortedArr.reduce((minDiff, current, index, array) => { // 跳过第一个元素,因为没有前一个元素可以比较 if (index === 0) return minDiff; const diff = Math.abs(current - array[index - 1]); return diff < minDiff ? diff : minDiff; }, Infinity); }
你可以根据自己的需求选:如果只是想把原来的双重循环换成reduce风格,第一个版本最适合;如果要纯函数式写法,就选双层reduce;如果追求极致性能,那排序后用reduce的版本绝对是首选。
备注:内容来源于stack exchange,提问作者Igor Shmukler
相关产品推荐
相关产品推荐

