LeetCode - 238. 除自身以外数组的乘积

目录

题目

核心思想

算法步骤

图解示例

时间和空间复杂度

读者可能出现的错误写法

正确的写法


题目

238. 除自身以外数组的乘积 - 力扣(LeetCode)

核心思想

使用双指针,将每个位置的结果分解为两部分的乘积:

  • 该位置左侧所有元素的乘积
  • 该位置右侧所有元素的乘积

算法步骤

创建结果数组:初始化为全1,因为乘法的单位元是1

   vector result(nums.size(), 1);

第一次遍历(从左到右):计算每个位置左侧所有元素的乘积

  • 维护一个变量left,表示当前位置左侧所有元素的乘积,初始值为1

对于每个位置i:

  • 将left的值乘到result[i]上
  • 更新left,乘上当前元素nums[i],为下一个位置做准备
   int left = 1;
   for(int i = 0; i < nums.size(); i++) {
       result[i] *= left;  // 当前位置乘以左侧乘积
       left *= nums[i];    // 更新左侧乘积
   }

第二次遍历(从右到左):计算每个位置右侧所有元素的乘积,并与之前结果相乘

  • 维护一个变量right,表示当前位置右侧所有元素的乘积,初始值为1
  • 对于每个位置i(从右往左):
  • 将right的值乘到result[i]上
  • 更新right,乘上当前元素nums[i],为下一个位置做准备

图解示例

对于数组 [1,2,3,4]:

  1. 初始化:result = [1,1,1,1]
  1. 第一次遍历(左→右):
  • i=0: left=1, result[0]=1*1=1, left=1*1=1
  • i=1: left=1, result[1]=1*1=1, left=1*2=2
  • i=2: left=2, result[2]=1*2=2, left=2*3=6
  • i=3: left=6, result[3]=1*6=6, left=6*4=24

此时 result = [1,1,2,6]

第二次遍历(右→左):

  • i=3: right=1, result[3]=6*1=6, right=1*4=4
  • i=2: right=4, result[2]=2*4=8, right=4*3=12
  • i=1: right=12, result[1]=1*12=12, right=12*2=24
  • i=0: right=24, result[0]=1*24=24, right=24*1=24

最终 result = [24,12,8,6]

时间和空间复杂度

  • 时间复杂度:O(n),只需要两次遍历数组
  • 空间复杂度:O(1),除了结果数组外,只使用了常数额外空间
   int right = 1;
   for(int i = nums.size()-1; i >= 0; i--) {
       result[i] *= right;  // 当前位置乘以右侧乘积
       right *= nums[i];    // 更新右侧乘积
   }

    读者可能出现的错误写法

    class Solution {
    public:
        vector productExceptSelf(vector& nums) {
            vector result(nums.size(),1);
            int left = 1;
    
            for(int i = 0; i< nums.size();i++)
            {
                left = nums[i];
                result  = result * left;
            }
    
            int right = 1;
            for(int i = n-1;i>0;i++)
            {
                right = nums[i];
                result  = result * right;
            }
            return result;
        }
    };

    left = nums[i]; - 这里是错误的赋值。应该是将当前结果乘以左侧乘积,然后更新左侧乘积。

    result = result * left; - 这是错误的语法。不能直接用向量乘以整数,需要对向量的每个元素进行操作。

    for(int i = n-1;i>0;i++) - 这里有三个问题:

    • 使用了未定义的变量 n(应该是 nums.size())
    • 循环条件应该是 i >= 0,否则会漏掉索引0
    • 递增运算符应该是 i--,否则会导致无限循环

    右侧遍历的逻辑也有问题,不应该直接赋值 right = nums[i]

    正确的写法

    class Solution {
    public:
        vector productExceptSelf(vector& nums) {
            vector result(nums.size(),1);
            int left = 1;
    
            for(int i = 0; i< nums.size();i++)
            {
    
                result[i]  = result[i] * left;
                left = left*nums[i]; //更新left
            }
    
            int right = 1;
            for(int i = nums.size()-1; i>=0; i--)
            {
                result[i]  = result[i] * right;
                right = right*nums[i]; //更新right
            }
            return result;
        }
    };

    你可能感兴趣的:(LeetCode大师之路,算法,leetcode,数据结构)