除自身以外数组的乘积的C++代码

C++实现数组乘积问题

除自身以外数组的乘积的C++代码

“除自身以外数组的乘积”问题要求在不使用除法且时间复杂度为 ​O(n)​​ 的条件下,计算数组中每个位置除自身外所有元素的乘积。以下是符合要求的 C++ 代码实现及详细解释:

优化解法代码(空间复杂度 O(1))

#include <vector>
using namespace std;

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> answer(n, 1);  // 结果数组初始化为1
        
        // 1. 计算前缀积(左侧所有元素的乘积)
        int prefix = 1;
        for (int i = 0; i < n; i++) {
            answer[i] = prefix;    // 存储当前位置的前缀积
            prefix *= nums[i];      // 更新前缀积(包含当前元素)
        }
        
        // 2. 计算后缀积(右侧所有元素的乘积)并合并结果
        int suffix = 1;
        for (int i = n - 1; i >= 0; i--) {
            answer[i] *= suffix;   // 前缀积 × 后缀积
            suffix *= nums[i];     // 更新后缀积(包含当前元素)
        }
        return answer;
    }
};

算法核心思想

  1. 两次遍历策略​:

    • 第一次遍历(从左到右)​​:计算每个位置左侧所有元素的乘积(前缀积),存储到 answer中。

      示例:对 nums = [1,2,3,4],遍历后 answer = [1, 1, 2, 6]

    • 第二次遍历(从右到左)​​:动态计算右侧所有元素的乘积(后缀积),与 answer中的前缀积相乘得到最终结果。

  2. 空间优化​:

    仅使用输出数组 answer和一个临时变量(suffix),空间复杂度 ​O(1)​​(输出数组不计入额外空间)。

处理特殊场景

  • 零值元素​:若数组中有零(如 nums = [-1,1,0,-3,3]),算法自动处理为:

    • 零值位置的结果 = 其他非零元素的乘积(如 answer[2] = (-1)×1×(-3)×3 = 9)。

    • 非零位置的结果 = 0(因包含零元素)。

  • 多个零值​:若存在两个及以上零值,所有结果自动为 0。

复杂度分析

指标

说明

时间复杂度

O(n)

两次独立遍历数组

空间复杂度

O(1)

仅用常量额外空间(除输出数组)

此解法满足题目所有约束,且是效率最优的实现方案。通过分离前缀积与后缀积的计算,避免除法并高效处理边界情况。

vector<int> answer(n, 1);  //是什么意思

在 C++ 中,vector<int> answer(n, 1);是一种 ​初始化动态数组(vector)​​ 的语法,具体含义如下:

📌 语句解析:

  1. vector<int>

    • 声明一个容器类型,用于存储整数(int)元素。

  2. answer

    • 自定义的变量名,代表这个动态数组的标识符。

  3. (n, 1)

    • 第一个参数 n​:指定容器的初始大小​(即包含 n个元素)。

    • 第二个参数 1​:指定容器中所有元素的初始值​(此处每个元素的值均为 1)。

⚙️ 功能说明:

  • 该语句会创建一个名为 answer的整数动态数组,其特点包括:

    • 长度(Size)​​:n

    • 每个元素的值​:均为 1

  • 例如:若 n = 5,则 answer的内容为 [1, 1, 1, 1, 1]


🔍 对比其他初始化方式:

初始化方式

含义

示例(n=3)​

vector<int> a(n);

创建大小为 n,元素值默认初始化​(通常为 0

[0, 0, 0]

vector<int> a(n, 1);

创建大小为 n,元素值均为 1

[1, 1, 1]

vector<int> a{1, 2, 3};

直接初始化列表,元素按给定值赋值

[1, 2, 3]

vector<int> a = {1, 2, 3};

同上(C++11 起支持)

[1, 2, 3]

💡 注意:​圆括号 ( )用于构造(指定大小和初值)​,而花括号 { }用于列表初始化​(直接赋具体值)。


🚀 典型应用场景:

  • 预分配空间​:提前为容器分配固定大小的内存,避免后续动态扩容的开销。

  • 统一初值​:在算法中需要所有元素初始化为特定值(如累乘/累加计算的初始状态)。

    示例:

    // 创建一个大小为 10 的 vector,所有元素初始化为 1
    vector<int> product_array(10, 1);  // 结果:[1, 1, ..., 1]

⚠️ 易混淆点:

  • vector<int> a{n};​:

    使用花括号时,若参数为单一整数,会创建一个包含一个元素 n​ 的容器(而非大小为 n)。

    示例:vector<int> a{5};→ 内容为 [5],而非 5 个元素。


✅ 总结:

vector<int> answer(n, 1);高效创建了一个长度为 n且所有元素值为 1的整数动态数组,适用于需要预分配空间并设置统一初始值的场景。

### 实现不使用法计算数组当前元素外其余元素乘积算法 该问题可以通过维护两个辅助数组 `L` 和 `R` 来解决,分别表示某个位置左侧所有元素的累积乘积和右侧所有元素的累积乘积。以下是具体的实现方式: #### Python 实现 ```python def productExceptSelf(nums): length = len(nums) L, R, answer = [0]*length, [0]*length, [0]*length # 初始化 L 数组 L[0] = 1 for i in range(1, length): L[i] = L[i-1] * nums[i-1] # 记录当前位置左侧所有元素的乘积[^1] # 初始化 R 数组 R[length-1] = 1 for i in reversed(range(length-1)): R[i] = R[i+1] * nums[i+1] # 记录当前位置右侧所有元素的乘积[^3] # 结合 L 和 R 的结果得到最终答案 for i in range(length): answer[i] = L[i] * R[i] # 当前位置的结果等于其左侧和右侧乘积之积 return answer ``` 上述代码通过两轮遍历完成任务,时间复杂度为 O(n),空间复杂度也为 O(n)。 --- #### Java 实现 ```java public class Solution { public static int[] productExceptSelf(int[] nums) { int length = nums.length; int[] L = new int[length]; int[] R = new int[length]; int[] answer = new int[length]; // 初始化 L 数组 L[0] = 1; for (int i = 1; i < length; i++) { L[i] = L[i - 1] * nums[i - 1]; // 记录当前位置左侧所有元素的乘积 } // 初始化 R 数组 R[length - 1] = 1; for (int i = length - 2; i >= 0; i--) { R[i] = R[i + 1] * nums[i + 1]; // 记录当前位置右侧所有元素的乘积 } // 结合 L 和 R 的结果得到最终答案 for (int i = 0; i < length; i++) { answer[i] = L[i] * R[i]; // 当前位置的结果等于其左侧和右侧乘积之积 } return answer; } } ``` Java 版本同样遵循相同的逻辑框架,利用额外的空间存储中间状态。 --- #### C++ 实现 ```cpp #include <vector> using namespace std; class Solution { public: vector<long long> productExcludeItself(vector<int>& nums) { int len = nums.size(); vector<long long> B(len); long long f[len + 1]; f[len] = 1; // 初始化 R 数组 for (int i = len - 1; i >= 0; --i) { f[i] = f[i + 1] * nums[i]; // 记录当前位置右侧所有元素的乘积 } long long tmp = 1; for (int i = 0; i < len; ++i) { B[i] = tmp * f[i + 1]; // 当前位置的结果等于其左侧和右侧乘积之积 tmp *= nums[i]; } return B; } }; ``` C++ 中采用了更紧凑的方式减少了一个辅助数组的需求,但仍保持清晰易懂的逻辑结构。 --- ### 总结 以上三种语言均实现了无需显式使用法即可求得目标数组的功能。核心思想在于分离处理每个元素左右两侧的信息并加以组合得出最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值