MST

星途 面试题库

面试题:JavaScript递归函数的性能优化及复杂应用

在JavaScript中,假设有一个非常大的嵌套数组,如下结构(仅为示例,实际可能嵌套更深、数组更大): ```javascript const largeNestedArray = [1, [2, [3, [4, [5]]]]]; ``` 编写一个递归函数来计算该嵌套数组所有元素的总和。由于可能存在深度嵌套,递归调用可能导致栈溢出问题,请在实现递归函数的同时,提出至少两种优化方案以避免栈溢出,并且说明每种优化方案的原理和适用场景。
43.2万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
// 递归函数计算嵌套数组总和
function sumNestedArray(arr) {
    let sum = 0;
    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            sum += sumNestedArray(arr[i]);
        } else {
            sum += arr[i];
        }
    }
    return sum;
}

// 优化方案1:使用尾递归优化(原理:在函数的最后一步调用自身,避免栈增长。适用场景:支持尾递归优化的环境,如现代的某些JavaScript引擎)
function sumNestedArrayTailRecursion(arr, sum = 0) {
    if (arr.length === 0) {
        return sum;
    }
    let current = arr.shift();
    if (Array.isArray(current)) {
        return sumNestedArrayTailRecursion([...current, ...arr], sum);
    } else {
        return sumNestedArrayTailRecursion(arr, sum + current);
    }
}

// 优化方案2:使用栈模拟递归(原理:手动维护一个栈结构来代替函数调用栈。适用场景:各种环境,尤其是不支持尾递归优化的环境)
function sumNestedArrayWithStack(arr) {
    let sum = 0;
    let stack = arr.slice();
    while (stack.length > 0) {
        let current = stack.pop();
        if (Array.isArray(current)) {
            stack.push(...current);
        } else {
            sum += current;
        }
    }
    return sum;
}
  1. 优化方案1:尾递归优化
    • 原理:尾递归是指在函数的最后一步调用自身,这样函数调用栈可以复用,不会随着递归深度增加而无限增长。在尾递归中,当前函数的调用帧可以被新的调用帧直接替换,因为不需要保留当前函数的上下文信息来计算返回值。
    • 适用场景:适用于支持尾递归优化的JavaScript引擎环境,例如现代的某些浏览器和Node.js版本。但并非所有环境都支持,需要注意兼容性。
  2. 优化方案2:使用栈模拟递归
    • 原理:手动维护一个栈数据结构,通过将数组元素压入栈中,然后依次弹出并处理,模拟递归调用的过程。这种方式避免了函数调用栈的无限增长,因为所有的递归状态都由手动维护的栈来管理。
    • 适用场景:适用于各种JavaScript环境,尤其是那些不支持尾递归优化的环境。它可以有效地处理深度嵌套的数组,因为栈的大小可以根据需要动态调整,而不会受到系统栈大小的限制。