Leetcode の毎日の質問 - 238. それ自体以外の配列の積 (インタビューの古典的な 150 の質問)

1. トピックの説明と要件

238. Self を除く配列の積 - LeetCode

トピックの説明

整数配列 nums を指定すると、answer[i] が nums[i] を除く nums 内のすべての要素の積に等しい配列 Answer を返します。

トピック データは、配列 nums 内のすべてのプレフィックス要素と任意の要素のサフィックスの積が 32 ビット整数の範囲内であることを保証します。

除算を使用せず、この問題を O(n) 時間の計算量で解決してください。

例 1:

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

例 2:

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

ヒント

  • 2 <= nums.length <= 105
  • -30 <= nums[i] <= 30
  • 配列 nums 内のすべてのプレフィックス要素と任意の要素のサフィックスの積が 32 ビット整数の範囲内であることを確認します。

2. 問題解決のアイデア

一般的なアイデア:

まずタイトルを分析すると、タイトルでは、指定された配列内の各要素自体を除くすべての要素の積を計算し、この積を回答配列に順番に格納する必要があることがわかり       ますこの要件に基づいて、二重の for ループを使用して解決することを考えることができますが、タイトルではO(n) 時間計算量内で完了する必要があります。この要件に基づいて、for ループを使用して、配列全体の積を求め、対応する要素で除算しますが、タイトルには除算は使用できないと記載されています。したがって、除算を使用せず、最大 1 層の for ループを使用して最終結果を求める必要があります。

      このようにして、各要素以外の数字がそれぞれ左辺と右辺に分布しているかどうかを解析することができますが、対応する答えを求める際に難しいのは、数字自体を読み飛ばしてしまうことです次に、対応する要素を分割線として使用して左側のすべての要素の積と右側のすべての要素の積を計算し、これら 2 つの積を乗算して最終結果を得ることができますか。左または右すべてを要求するだけでよいため、スキップする必要がなく、for ループの層を使用して結果を直接取得できます。明らかに、レコードに対応する左要素積と右要素積もデータを格納するために配列を使用します。

       最初の要素と最後の要素には左側(右側)の要素がないため、左側の積を計算する場合は i が 1 から始まり、右側の積を計算する場合は i が numsSize-2 から始まります。左積を計算する式は left[i]=left[i-1]*nums[i-1] ですleft[i] の意味は、配列内の添え字 i の要素の左要素の積を指します。そのため、現在の要素の左積は、前の数値の左側の積に前の数値を乗算することで取得できます。 。右側にも同じことが当てはまります。right[i]=right[i+1]*nums[i+1] ですそれらを別々に計算した後、2 つの結果を直接乗算し、その値を応答配列に割り当てます。

具体的な手順:

① 結果を格納するために使用する 2 つの配列と最終的に返される配列を定義します

②各要素の左側にあるすべての要素の積を求め、左側の配列に格納します

③ 各要素の右側にあるすべての要素の積を求め、適切な配列に格納します。

④左の積と右の積の積を求め、答えの配列に格納する

⑤ 答えの配列を返す


3. 具体的なコード【C言語】

/**
 * Note: The returned array must be malloced, assume caller calls free().
   意思是:返回的数组要利用malloc申请空间
 */
int* productExceptSelf(int* nums, int numsSize, int* returnSize){
    //要求计算除自身以外数组的乘积,如果不限制时间复杂度则可以直接利用双重循环求结果
    //但题目要去时间复杂度为O(n),因此我们最多只能够使用一层for循环
    //所要得到的乘积可以转变成分别求其左右两边的乘积后相乘的结果。
    int left[numsSize];//用来存储每个数的左边乘积
    int right[numsSize];//用来存储每个数的右边乘积
    *returnSize = numsSize;//返回数组的大小与原数组相等
    int * answer = (int *)malloc(sizeof(int) * numsSize);//为answer数组申请空间

    //左乘积
    left[0] = 1;//相乘而不是加减,所以初始化为1
    //第一个元素左边没有数据,因此从下标为1的元素开始计算
    for(int i = 1; i < numsSize; i++)
    {
        left[i] =  left[i-1] *  nums[i-1];//计算不包括自身在内的左边的数的乘积
    }

    //右乘积
    right[numsSize-1] = 1;
    //最后一个元素的右边没有数据,因此从下标为numsSize-2开始计算
    for(int i = numsSize-2; i  >= 0 ; i--)
    {
        right[i] =  right[i+1] *  nums[i+1];//计算不包括自身在内的右边的数的乘积
    }
    for(int i =0; i < numsSize; i++)
    {
        answer[i] = left[i] * right[i];//将每个数左右两边的乘积相乘得到最后结果
    }
    return answer;
}

おすすめ

転載: blog.csdn.net/m0_59800431/article/details/131656783