题目描述 给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4] 输出: [24,12,8,6]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/product-of-array-except-self
暴力方法: 1.要求nums的各个数相乘,除了当前的序号,并将结果放进当前序号中 2.首先第一层for循环,确定当前的序号,第二个for循环遍历所有数字 3.如果等于当前序号,就不相乘,其他情况都乘上对应的数字 4.没有通过测试用例,时间超时。
vector<int> productExceptSelf(vector<int>& nums) {
int m = nums.size();
vector<int> ret(m);
for(int i = 0; i < m; i++) {
int sum = 1;
for(int j = 0; j < m; j++) {
if(i != j) {
sum *= nums[j];
}
}
ret[i] = sum;
}
return ret;
}
题目说:整个数组的乘积都在整数可表达的范围内 下面的方案不可行。
vector<int> productExceptSelf(vector<int>& nums) {
int m = nums.size();
vector<int> ret(m);
int sum = 1;
for(int i = 0; i < m; i++) {
sum *= nums[i];
}
for(int i = 0; i < m; i++) {
ret[i] = sum / nums[i];
}
return ret;
}
这个是我看到官网的提示的时候,想出来的,那里面提到了前缀和还有后缀和 1.首先我在这个位置创建m+1的前缀和还有m+1的后缀和数组 2.这里prefix[0] = suffix[m] = 1 3.计算前缀和,还有后缀和 4.计算每个位置的和,那么每个位置的话,就是前一个的前缀和乘以后一个的后缀和为当前序号的结果 空间复杂度是O(2m+2),即O(m) 时间复杂度是O(m)
vector<int> productExceptSelf(vector<int>& nums) {
int m = nums.size();
vector<int> prefix(m + 1), suffix(m + 1);
prefix[0] = suffix[m] = 1;
for(int i = 1; i <= m; i++) {
prefix[i] = prefix[i - 1] * nums[i - 1];
}
for(int i = m - 1; i >= 0; i--) {
suffix[i] = suffix[i + 1] * nums[i];
}
for(int i = 0; i < m; i++) {
nums[i] = prefix[i] * suffix[i + 1];
}
return nums;
}
上面记录的前缀和还有后缀和都多了占用了一个位置,其实不用n+1位置,n个位置就够了
vector<int> productExceptSelf(vector<int>& nums) {
int m = nums.size();
vector<int> prefix(m), suffix(m);
prefix[0] = suffix[m - 1] = 1;
for(int i = 1; i < m; i++) {
prefix[i] = prefix[i - 1] * nums[i - 1];
}
for(int i = m - 2; i >= 0; i--) {
suffix[i] = suffix[i + 1] * nums[i + 1];
}
for(int i = 0; i < m; i++) {
nums[i] = prefix[i] * suffix[i];
}
return nums;
}
时间复杂度是O(m) 空间复杂度不算输出向量是O(1)
vector<int> productExceptSelf(vector<int>& nums) {
int m = nums.size();
vector<int> ret(m);
ret[0] = 1;
for(int i = 1; i < m; i++) {
ret[i] = ret[i - 1] * nums[i - 1];
}
int temp = nums[m - 1];
nums[m - 1] = 1;
for(int i = m - 2; i >= 0; i--) {
int temp_swap = nums[i];
nums[i] = nums[i + 1] * temp;
temp = temp_swap;
}
for(int i = 0; i < m; i++) {
ret[i] = ret[i] * nums[i];
}
return ret;
}
这里首先创建前缀和数组,而动态的创建后缀和数组。 直接将前缀和乘以后缀和,得到的结果放到对应的ret矩阵中
vector<int> productExceptSelf(vector<int>& nums) {
int m = nums.size();
vector<int> ret(m);
ret[0] = 1;
for(int i = 1; i < m; i++) {
ret[i] = nums[i - 1] * ret[i - 1];
}
int R = 1;
for(int i = m - 1; i >= 0; i--) {
ret[i] = ret[i] * R;
R *= nums[i];
}
return ret;
}
int main() {
vector<int> nums = {1, 2, 3, 4, 5};
productExceptSelf(nums);
}
写到这里,我在https://leetcode-cn.com/circle/article/48kq9d/这篇文章中的数组部分算是做完了,这其中有悲伤有快乐,更多的是收获,感觉这部分的技巧性占大部分,当然也有的解题方法,但是我一直感觉刷题就应该刷动态规划、分支限界法这种的,但是,我也不知道下一步应该做什么,如果感觉我的方向不对的,可以在评论告诉我。或者你有好的方法,提升算法能力的。
|