自分以外の配列の積(C言語で詳しく解説)

トピック: それ自体を除く配列の積

        整数配列numsを指定すると、配列Answerを返します。 ここで、answer[i] は、nums[i]を除くnumsの残りの要素の積に等しくなります。

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

除算は使用せず、この問題をO(n)時間以内に完了してください

ヒント:

 2 <= nums.length <= 10^5

-30 <= nums[i] <= 30

配列内のすべてのプレフィックス要素と任意の要素のサフィックスの積が 32 ビット整数の範囲 nums 内にあることを確認します。

例 1:

入力: nums=[1, 2, 3, 4]

出力: [24、12、8、6]

例 2:

入力: nums=[-1,-1,0,-3,3]

出力: [0、0、9、0、0]

問題解決のアイデア:

2 つの配列(プレフィックス積配列とサフィックス積配列)を定義します。プレフィックス配列はleft []、サフィックス配列はright [] です。

左 [ i ]にはnums [ i ]の前の積の合計が格納され右 [ i ] にはnums [ i ]の後の積の合計が格納されます(空の場合は 1 が格納されます)。

動的メモリ変数を作成します。 int* ret=(int*)malloc(sizeof(int)*numsSize);

次に、ret [ i ] = left [ i ] * right [ i ]、保存後に戻ります。

アイデアの実装:

配列要素: 2 <= nums.length <= 10^5であるため

したがって、プレフィックス配列とサフィックス配列に要求される配列サイズは両方とも10^5 です。

int left[100000]={0};
int right[100000]={0};

次に、プレフィックス積配列の値を走査します。

    //前缀乘积和
    for(i=0;i<numsSize;i++)
    {
        if(i==0)
        {
            left[i]=1;
        }
        else
        {
            left[i]=left[i-1]*nums[i-1];
        }
    }

分析:

ここでは例として 配列nums [1, 2, 3, 4, 5, 6] を使用します。

このとき、 left [ 0 ] = 1 となり、 left [ 1 ] = left [ 0 ] * nums [ 0 ] は left [ 1 ] = nums [ 0 ] と同等になります。

left[2] = left[1] * nums[1] は left[2] = nums[0] * nums[1] に相当します。

left[3] = left[2] * nums[2] は left[3] = nums[0] * nums[1] * nums[2] に相当します。

。。。。。。

left[5] = left[4] * nums[4] は left[5] = nums[0] * nums[1] * nums[2] * nums[3] * nums[4] に相当します。

誰もがそのパターンを見つけたと思います。

次に、接尾辞の積配列の値を走査します。

   //后缀乘积和
    for(i=numsSize-1;i>=0;i--)
    {
        if(i==numsSize-1)
        {
            right[i]=1;
        }
        else
        {
            right[i]=right[i+1]*nums[i+1];
        }
    }

分析:

同様に: nums [1, 2, 3, 4, 5, 6]

left [ 5 ] =1 の場合、 left [ 4 ] = left [ 5 ] * nums [ 5 ] は left [ 4 ] = nums [ 5 ] と同等です。

left[3] = left[4] * nums[4] は left[3] = nums[4] * nums[5] に相当します。

left[2] = left[3] * nums[3] は left[2] = nums[3] * nums[4] * nums[5] に相当します。

。。。。。。

left[0] = left[1] * nums[1] は left[0] = nums[1] * nums[2] * nums[3] * nums[4] * nums[5] に相当します。

次に、戻り値 (* returnSize) に値を代入し、動的インナー (ret) を作成し、それに値を代入してから戻ります。

    * returnSize=numsSize;
    int* ret=(int*)malloc(4*numsSize);
    //给返回指针赋值
    for(i=0;i<numsSize;i++)
    {
        ret[i]=left[i]*right[i];
    }

時間計算量は(O(N)) です。

これがこの質問の基本的な考え方であり、プログラムのソースコードは次のとおりです。

int* productExceptSelf(int* nums, int numsSize, int* returnSize){
    int i=0;
    int left[100000]={0};
    int right[100000]={0};
    //前缀乘积和
    for(i=0;i<numsSize;i++)
    {
        if(i==0)
        {
            left[i]=1;
        }
        else
        {
            left[i]=left[i-1]*nums[i-1];
        }
    }
    //后缀乘积和
    for(i=numsSize-1;i>=0;i--)
    {
        if(i==numsSize-1)
        {
            right[i]=1;
        }
        else
        {
            right[i]=right[i+1]*nums[i+1];
        }
    }
    * returnSize=numsSize;
    int* ret=(int*)malloc(4*numsSize);
    //给返回指针赋值
    for(i=0;i<numsSize;i++)
    {
        ret[i]=left[i]*right[i];
    }
    return ret;
}

不足がある場合は、お気軽に補足して連絡してください。

終わり。


        

おすすめ

転載: blog.csdn.net/m0_71676870/article/details/132303752