leetcode_238:除自身以外数组的乘积

这个题目就是《剑指offer》上面的面试题66。刚开始就是按照上面的思路然后构造了两个数组pre和last,分别记录从前往后的累乘积和从后往前的累乘积,然后再遍历一次得到result,其中result[i] = pre[i-1] * last[i+1]。代码如下:

    public static int[] productExceptSelf(int[] nums) {
        int numLength = nums.length;
        int[] pre = new int[numLength];
        pre[0] = nums[0];
        int[] last = new int[numLength];
        last[numLength-1] = nums[numLength-1];

		//开始构造pre和last两个数组
        for (int i = 1, j = numLength-2; i < numLength && j >= 0; i++, j--) {
            pre[i] = pre[i-1] * nums[i];
            last[j] = last[j+1] * nums[j];
        }

        int[] result = new int[numLength];
        //得到result数组
        for (int i = 1; i < numLength-1; ++i) {
            result[i] = pre[i-1] * last[i+1];
        }
        //两端的值单独处理
        result[0] = last[1];
        result[numLength-1] = pre[numLength-2];
        return result;
    }

当然这样做的时间复杂度是O(2n)(或者O(n)),空间复杂度为O(2n),result不算在里面。题目说能否使得空间复杂度为常量,思考一番还是无果,于是看了其他人的实现,也是看了好一会才懂。先看一下代码:

    public static int[] productExceptSelf1(int[] nums) {
        int numLength = nums.length;
        int[] result = new int[numLength];
        for (int i = 0; i < numLength; ++i)
            result[i] = 1;
        int left = 1, right = 1;
        //一个循环就搞定了
        for (int i = 0; i < numLength; ++i) {
            result[i] *= left;
            left *= nums[i];

            result[numLength-1-i] *= right;
            right *= nums[numLength-1-i];
        }
        return result;
    }

主要是看看后面那个for循环,这里很巧妙只遍历了一次就计算出了所有结果。我们将这个步骤分为两步:

  1. 首先分别计算左边的累乘结果和右边的累乘结果,直到左右指针相遇时。
  2. 然后右边的指针就可以直接利用左边的累乘结果更新左边的结果,左边的指针也可以利用右边的累乘结果更新右边的结果。

上一个图就能看的比较清晰。要知道left和right的更新只和nums有关,而result的更新则只与left、right都有关,绿色的线表示这一步要进行的乘法操作。
在这里插入图片描述
在这里插入图片描述

发布了96 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/reachwang/article/details/103336351
今日推荐