LeetCodeは毎日ブラシをかけます---古典的なインタビューの質問のシーケンステーブルを把握します

コンテンツ

1.要素を削除します

2.ソートされた配列の重複を削除します

3.2つのソートされた配列をマージします


1.要素を削除します

  • 直接リンク:

https://leetcode-cn.com/problems/remove-element/

  • トピック:

  • アイデア:

方法1:データを順番に移動してカバーする

図に示すように、最初のデータから、例1のように順番にトラバースされ、配列を順番にトラバースし、削除された要素2を見つけて、次のデータを前方に移動してカバーします。

 この方法には欠陥があります。タイトルは、この問題を解決するために空間計算量O(1)法が使用され、この方法の空間計算量はO(1)であることを明確に示しています。最悪の場合、 O(N ^ 2)であり、すべての値が存在する場合、n-1 + n-2 +が移動します...等差数列が表示され、時間計算量はO(N ^ 2)です。法則は最適ではありません、 それを変更。

方法2:ダブルポインタ1.0

元の配列を順番にトラバースしてvalであるかどうかを確認し、valではない値を新しい配列にコピーします。このメソッドの時間計算量はO(N)であり、空間計算量もO(N)ですが、タイトルは、スペースの複雑さがO(1)であることを明確に示しているため、このメソッドは機能しませんが、このメソッドをダブルポインターに引き続き使用するが、配列を開かない場合は、慎重に検討してください。元の配列を変更しますか?、これはDoublePointer2.0につながります

方法3:ダブルポインター2.0

このメソッドは、2番目のメソッドに基づくアップグレードです。2番目のメソッドは追加のアレイを開く必要があり、このメソッドは元のアレイを直接変更します。最初に2つの変数srcとdstを0として定義し、両方とも配列numsの添え字として、次にsrcをトラバースして、nums [src]がvalであるかどうかを確認します。そうでない場合は、添え字dstに割り当て、次にsrc ++、dst++を割り当てます。nums [src] = nums [dst]の場合、src ++とdstのみが変更されず、最後に長さdstを返すことができます。

  • コードは次のように表示されます。
int removeElement(int* nums, int numsSize, int val){
    int dst=0;
    int str=0;
    while(str<numsSize)
    {
        if(nums[str]==val)
        {
            str++;
        }
        else
        {
            nums[dst]=nums[str];
            dst++;
            str++;
        }
    }
    return dst;
}

2.ソートされた配列の重複を削除します

  • 直接リンク:

https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

  • トピック:

  • アイデア:

ダブルポインタ(配列を追加で開かないでください)

このタイトルは前のタイトルと似ています。ダブルポインタを使用して元の配列に変更を加えることもできます。配列numsの添え字として、dstとsrcの2つの変数を定義するだけで済みます。ただし、わずかな変更が加えられています。このとき、srcは添え字1から始まり、dstは添え字0から始まります。nums[src]を前のnums[src-1]と比較し、等しい場合はsrc ++、そうでない場合はnums[src-1]をnums[dst]に割り当て、次にdst ++、src++を割り当てます。

知らせ:

上記の操作を実行した後も問題があります。つまり、この質問の例のように、srcが最後から2番目の値3になると、srcの最後の添え字の値がnums[dst]に入れられません。は前の3と同じです。このとき、++ srcが必要です。nums[src]は4で、前の値とは異なります。nums[dst]に3を割り当てます。このとき、srcは++です。再び空にすると、データがなく、4が比較されて範囲外になるため、4が失われます。最後の2つの数値が両方とも3の場合、それらは常に等しいため、srcも+で空になり、3も失われるため、いずれの場合も、最後の数値をnums[dst]に移動します。

  • 描画デモ:

  • コードは次のように表示されます。
int removeDuplicates(int* nums, int numsSize){
    int dst=0;
    int src=1;
    while(src<numsSize)
    {
        if(nums[src]==nums[src-1])
        {
            src++;
        }
        else
        {
            nums[dst]=nums[src-1];
            dst++;
            src++;
        }
    }
    nums[dst]=nums[numsSize-1];
    dst++;
    return dst;
}

3.2つのソートされた配列をマージします

  • 直接リンク:

ソートされた2つの配列をマージする

  • トピック:

  • アイデア:

方法1: memmove +ソートソート(バブリング、qsortなど)

この方法は確かに可能ですが、タイトルにO(N)の時間計算量で問題を解決する必要があることが明確に示されている場合、バブリングの時間計算量はO(N ^ 2)であるため、この方法は機能しません。 )、およびqsortの時間計算量はO(N * logN)です。O(N)もそうではないので、交換する必要があります。

方法2: 1.0をマージする

順番に比較し、小さい方を毎回マージされた配列に入れます。このメソッドは、サードパーティのアレイを開く必要があります。次に、配列nums1、nums2、およびaの最初の添え字を表すために3つの変数i、j、およびdstを定義する必要があります。nums1[i] <nums [j]の場合、a [dst ++] = nums1 [i ++]、それどころか、a [dst ++] = nums2 [i ++]を順番にトラバースし、そのうちの1つが終了したら、残りをすべて配列に入れます。このメソッドの最大の問題は、追加の配列を開く必要があることです。時間とスペースを交換すると、O(N)のスペースが複雑になりますが、次のように、この方法に基づいてアップグレードできます。

法3:マージ2.0

この方法は、2番目の方法に基づいてアップグレードし、nums1の元の配列に直接変更を加えることです。考え方は2番目の方法と似ています。ただし、変更する必要があることが1つあります。2番目の方法は配列を前方にトラバースすることですが、このルールは配列を後方にトラバースする必要があります。この場合、このときのi変数はnums1配列のm-1添え字、j変数はnums2配列のn-1添え字、dst変数はnums1配列の最後の要素の添え字(m + n-1)。実現原理は2番目の方法と同じなので、詳しくは説明しません。:nums2配列の添え字jが最初に終了する場合は、nums1の残りの配列が直前にあり、移動する必要はありません。nums1配列の添え字iが最初に終了する場合は、残りの値を割り当てる必要があります。 nums2配列からnums1配列へ。上に移動します。

  • 描画デモ:

  •  コードは次のように表示されます。
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int i=m-1;
    int j=n-1;
    int dst=m+n-1;
    while(i>=0&&j>=0)
    {
        if(nums1[i]>nums2[j])
        {
            nums1[dst--]=nums1[i--];
        }
        else
        {
            nums1[dst--]=nums2[j--];
        }
    }
    while(j>=0)
    {
        nums1[dst--]=nums2[j--];
    }
}

おすすめ

転載: blog.csdn.net/bit_zyx/article/details/123578575