アルゴリズム通関村 - ダブルポインターの魔法の使い方 (要素トピックの削除)

1. ダブルポインタートピック

高速ポインタと低速ポインタ
衝突ポインタ

1.要素を削除する

要素の削除
配列 nums と値 val を指定すると、値が val に等しいすべての要素をその場で削除し、削除された配列の新しい長さを返す必要があります。
余分な配列スペースを使用しないでください。O(1) の追加スペースのみを使用し、入力配列をインプレースで変更する必要があります。
要素の順序は変更できます。新しい長さを超える配列内の要素を考慮する必要はありません。

1.2 分析

1.2.1 ダブルポインタ方式

slowポインタとfastポインタをslowポインタより前のデータにvalが含まれないように設定し、fastは逆方向に移動し、valでない場合はslow位置にfastの値を書き込みます。前半はうまくいきますが、後半はうまくいきません

 public int removeElement(int[] nums, int val) {
    
    
        int slow =0;
        for(int fast =0; fast<nums.length; fast++){
    
    
            if(nums[fast]!=val){
    
    
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }

ここに画像の説明を挿入
時間計算量: O(n) は配列の長さを走査します
空間計算量: O(1) は配列の長さを記録するために低速を使用します

1.2.2 ダブルポインタの衝突

左右のポインタを設定し、左側が val である場合を置き換える右側の val ではない値を見つけ、左側の要素も有効です。

    public int removeElement(int[] nums, int val) {
    
    
        int left =0;
        int right = nums.length -1;
        for(left =0;left<=right;){
    
    
            if(nums[right]!=val && nums[left] == val){
    
    
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right]=temp;
            }

            if(nums[left]!=val) left++;
            if(nums[right]==val) right--;
        }
        return left;
    }

ここに画像の説明を挿入
時間計算量: O(n) は配列の長さを走査します
空間計算量: O(1)

1.2.3 ダブルポインタの衝突+上書き

衝突するダブル ポインターは引き続き使用されますが、今回は、左右の配列要素を交換する代わりに、右側の要素が左側の要素を直接上書きします。

    public int removeElement(int[] nums, int val) {
    
    
        int right = nums.length -1;
        for(int left = 0;left<=right;){
    
    
            if(nums[left] == val){
    
    
                nums[left] = nums[right];
                right--;
            }else{
    
    
                left++;
            }
        }
        return right+1;
    }

ここに画像の説明を挿入

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

順序付けられた配列内の重複を削除する
配列番号が昇順に指定されている場合、各要素が 1 回だけ表示されるように、繰り返し要素をその場で削除し、削除された配列の新しい長さを返してください。要素の相対的な順序は一貫している必要があります。次に、一意の要素の数を nums で返します。

nums の一意の要素の数が k であることを考慮すると、ソリューションが確実に合格できるようにするには、次のことを行う必要があります。

nums の最初の k 要素に、最初に nums に出現した順序で一意の要素が含まれるように、配列 nums を変更します。nums の残りの要素は、nums のサイズには影響しません。
kを返します。

2.1 分析

2.1.1 高速ダブル ポインタと低速ダブル ポインタの使用

高速ポインタと低速ポインタは依然として設定されており、高速ポインタと低速ポインタが異なる場合にのみ低速ポインタを置き換えることができ、その後、低速ポインタが再びインクリメントされます。小さな最適化ポイントがあります。slow=0 を最初に処理する必要がないのは、0 と同じインデックスを持つ要素が後からある場合、後者の要素を置き換えるだけで済むためです。

public int removeDuplicates(int[] nums) {
    
    
        int slow =1;
        for(int fast =0; fast<nums.length;fast++){
    
    
            if(nums[fast]!=nums[slow-1]){
    
    
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }

ここに画像の説明を挿入
時間計算量: O(n)
空間計算量: O(1)

要約する

指定された要素を削除するというこの質問では、高速ポインタと低速ポインタを使用する効率が依然として非常に高く、このトピックを通じて、ダブル ポインタの一般的な使用方法をいくつか学びました。

おすすめ

転載: blog.csdn.net/qq_52843958/article/details/131921034