Solved
Given an integer array nums
, return an array answer
such that answer[i]
is equal to the product of all the elements of nums
except nums[i]
.
The product of any prefix or suffix of nums
is guaranteed to fit in a 32-bit integer.
You must write an algorithm that runs in O(n)
time and without using the division operation.
Example 1:
Input: nums = [1,2,3,4] Output: [24,12,8,6]
Example 2:
Input: nums = [-1,1,0,-3,3] Output: [0,0,9,0,0]
Constraints:
2 <= nums.length <= 105
-30 <= nums[i] <= 30
- The product of any prefix or suffix of
nums
is guaranteed to fit in a 32-bit integer.
Follow up: Can you solve the problem in O(1)
extra space complexity? (The output array does not count as extra space for space complexity analysis.)
google 翻譯:
給定一個整數數組 nums,傳回一個數組answer,使得 answer[i] 等於 nums 中除 nums[i] 之外的所有元素的乘積。
nums 的任何前綴或後綴的乘積保證適合 32 位元整數。
您必須編寫一個在 O(n) 時間內運作且不使用除法運算的演算法。
想法一:
因為不能用除法,每個數值,要跟其他所有的數值相乘。
最簡單的做法就是跑兩次迴圈...
(如果可以使用除法,做法會是無差別的,用 for 把所有數值都相乘起來。
再跑一次 for 把乘積除以目前用 for 輪到的數值)
寫法一:
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
int i, j;
int *result = malloc(sizeof(int) * numsSize);
// (每個數值,都要跟其他所有的數值相乘)
// 主要的 for 從頭跑到尾
for(i=0; i<numsSize; i++) {
result[i] = 1; // 因為要相乘,所以給定初始值 1
// 第二個 for 除了自己以外,都要相乘
for(j=0; j<numsSize; j++) {
if(i != j)
result[i] *= nums[j];
}
}
*returnSize = numsSize;
return result;
}
結果一:
這最簡便的寫法看來執行太久了...想辦法增加速度囉...想法二:
先算好兩組乘積,
第一組乘積從左邊開始往右邊相乘(假設乘積結果為 1(左一) 2(左二) 4(左三) 8(左四)),
第二組乘積從右邊開始往左邊相乘(假設乘積結果為 8(右一) 4(右二) 2(右三) 1(右四))。
回傳的陣列,從這兩乘積左右各抓取一筆相鄰的數值相乘即可,如:
回傳一 右二 (因為是開頭,所以右二就是答案了)
回傳二 左一 * 右三 (略過自己的位置,左右各取相鄰的一個相乘)
回傳三 左二 * 右四 (略過自己的位置,左右各取相鄰的一個相乘)
回傳四 左三 (因為是結尾,所以左三就是答案了)
寫法二:
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
int i, max;
int *result = malloc(sizeof(int) * numsSize);
int *data1 = malloc(sizeof(int) * numsSize); // 第一組乘積
int *data2 = malloc(sizeof(int) * numsSize); // 第二組乘積
// 第一組乘積計算,從左邊開始
for(i=0; i<numsSize; i++) {
if(i == 0) // 開頭放自己即可
data1[i] = nums[i];
else
data1[i] = data1[i-1] * nums[i];
}
// 第二組乘積計算,從右邊開始
for(i=numsSize-1; i>=0; i--) {
if(i == numsSize-1) // 結尾放自己即可
data2[i] = nums[i];
else
data2[i] = data2[i+1] * nums[i];
}
// 回傳值計算
for(i=0; i<numsSize; i++) {
if(i == 0) // 開頭直接抓值
result[i] = data2[i+1];
else if(i == numsSize-1) // 結尾直接抓值
result[i] = data1[i-1];
else // 中間的要左右各抓一個相鄰的值相乘
result[i] = data1[i-1] * data2[i+1];
}
free(data1);
free(data2);
*returnSize = numsSize;
return result;
}
結果二:
結果雖然差強人意,但至少有成功了。再想優化的方法...想法三:
把從左邊和從右邊的兩組乘積陣列省略
直接使用要回傳的陣列暫存,也少跑了一次 for
寫法三:
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
int i, product;
int *result = malloc(sizeof(int) * numsSize);
// 計算從左邊開始的乘積陣列
product = 1;
for(i=0; i<numsSize; i++) {
result[i] = product;
product *= nums[i];
}
// 計算從右邊開始的乘積陣列,一併直接計算出回傳結果
product = 1;
for(i=numsSize-1; i>=0; i--) {
result[i] *= product;
product *= nums[i];
}
*returnSize = numsSize;
return result;
}
結果三:
結果不是很好,但可以接受了,也沒有想改的部份了,就這樣吧...
沒有留言:
張貼留言