LeetCode238.除自身以外数组的乘积(c++实现)

除自身以外数组的乘积(c++实现)

首先看题目:

给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中
除 nums[i] 之外其余各元素的乘积。

示例:

输入: [1,2,3,4]
输出: [24,12,8,6]

提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。

说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。

进阶:
你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/product-of-array-except-self

分析:

首先,如果用没有除法限制问题会简单很多,一次遍历求出数组的所有元素的乘积,然后再遍历一次将乘积除以元素,就是结果值。但是这样会存在两个问题:

  • 1.如果有一个元素等于0,那该法失效
  • 2.如果所有元素的乘积大于 INT_MAX,结果溢出数据也会不准确

实现思路:

既然题目提示了用前缀和后缀的乘积,那我们可以遍历数组,取每个元素的前缀元素乘积和后缀元素乘积,然后前后缀乘积再相乘即是结果,比如
数组:arr[0~n] , arr[1]除自身以外数组的乘积=(前缀乘积arr[0]) * (后缀乘积 arr[2]*…arr[n])
下面是实现代码:

	vector<int> productExceptSelf(vector<int>& nums) {
    
    
        int len = nums.size();
        vector<int > res(len, 1);
        vector<int > left(len, 1);
        vector<int > right(len, 1);
        for (int i = 1; i < len; i++) {
    
    
        	//注:arr[0] 没有前缀乘积默认为1, arr[len-1] 没有后缀乘积, 默认为1
            left[i] = left[i - 1] * nums[i - 1];	//记录每个元素的前缀乘积
            right[len - i - 1] = right[len - i] * nums[len - i];	记录每个元素的后缀乘积
        }
        for (int i = 0; i < len; i++) {
    
    
            res[i] = left[i] * right[i];
        }
        return res;
    }

优化方案:

从代码可以看出,时间复杂度是O(n),空间复杂度是O(n),该法还有优化的空间,可将空间复杂度优化至O(1),即出输出数组res外,仅用常量级别空间;
思路是:先用res代替left存入每个元素的前缀乘积,第二次再用一个常量temp保存当前元素的后缀乘积,temp * res[i] 即是 arr[i]的.除自身以外数组的乘积。
下面是实现代码:

	vector<int> productExceptSelf(vector<int>& nums) {
    
    
        int len = nums.size();
        vector<int > res(len, 1);
        for (int i = 1; i < len; i++) {
    
    
            res[i] = res[i - 1] * nums[i - 1];	//记录每个元素的前缀乘积
        }
        int temp = 1;
        for (int i = len - 2; i >= 0; i--) {
    
    
            temp *= nums[i + 1];	//记录当前元素的后缀乘积
            res[i] = res[i] * temp; //当前元素的前缀乘积 * 当前元素的后缀乘积
        }
        return res;
    }

猜你喜欢

转载自blog.csdn.net/h799710/article/details/106569682
今日推荐