今天的题目如下所示:
这道题主要的难点在于不使用除法,而且要在O(n)的时间复杂度下完成题目。
既然时间上有限制,那就应该考虑用空间换取时间。想了一下之后,我觉得可以通过创建一个前向累积列表和一个后向累积列表来解决这个问题。为了能让自己更好地理解问题,我还专门画了图来帮助自己理解问题。
现在思路有了,直接开写。代码如下:
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
# rev_nums = nums[::-1]
forward = [1] * len(nums)
backward = [1] * len(nums)
for i in range(1,len(nums)):
forward[i] = nums[i-1] * forward[i-1]
# backward[i] = rev_nums[i-1] * backward[i-1]
backward[len(nums)-1-i] = nums[len(nums)-i] * backward[len(nums)-i]
result = []
# backward = backward[::-1]
for i in range(len(nums)):
result.append(forward[i]*backward[i])
return result
这里包括两种原理一样但是处理方法不一样的解法,被注释的其中一种。在这里我觉得比较奇怪的是,为什么多了两次倒序转换的被注释的那种方法竟然比代码里的这种方法运行要快……
为了不丢掉上个学期学的C++,我决定从今天开始捡起C++,每次用python写完之后用C++再写一遍。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int length = nums.size();
int forward[length];
int backward[length];
vector<int> result;
forward[0] = 1;
backward[length-1] = 1;
for(int i=1; i < length;i++){
forward[i] = nums[i-1]*forward[i-1];
backward[length-1-i] = nums[length-i]*backward[length-i];
}
for(int j=0;j<length;j++){
result.push_back(forward[j]*backward[j]);
}
return result;
}
};
写是写好了,但是感觉效率都不太行……之后还得慢慢学怎么优化代码质量呀!
想了一下,可以尝试一下继续降低空间复杂度来提升代码质量。根据题目中的提示,输出数组可以不被视为额外空间,那就可以考虑把其中一个列表简化成数字,另外一个数组作为输出数组,这样空间复杂度就为O(1)了(只有那个数字是额外空间)。
这次的Python代码如下所示:
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
forward = [1] * len(nums)
backward = 1
for i in range(1,len(nums)):
forward[i] = nums[i-1] * forward[i-1]
for i in range(len(nums)-1, -1, -1):
forward[i] *= backward
backward *= nums[i]
return forward
这个方法运行速度提高了,空间复杂度也降低了。
依葫芦画瓢,把C++的代码也写一下:
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int length = nums.size();
int backward = 1;
vector<int> result(length, 1);
for(int i=1; i < length;i++){
result[i] = nums[i-1]*result[i-1];
}
for(int j=length-1;j>=0;j--){
result[j] = result[j]*backward;
backward *= nums[j];
}
return result;
}
};
在C++下用这种方法速度是快了一点,但是内存消耗还是很高,看来还得继续学慢慢优化😂