leetcode 1989 のような問題は 2 つの部分に分割できるため、二分法の適用範囲が広がります。

1898. 削除できる最大文字数

中程度の難易度 34 のお気に入りと共有 英語に切り替えて動的フィードバックを受け取ります

s 2 つの文字列と が 与えられます p 。 は の部分 列 p です  。同時に、要素が 互いに異なり 、添え字が 0 から 数え 始める整数配列が与えられます。 この配列は  添え字のサブセットです ( 添え字も 0 から数え始めます )。sremovabless

整数 k( 0 <= k <= removable.length) を見つけて、 removable その中の 最初の  添え字 k を選択し、 これらの添え字に対応する文字を削除してください。整数は  次の条件を満たす必要があります。上記の手順を実行した後も、  整数は依然として の 部分 です 。より正式な説明は、それぞれの について  、まず  文字を でマークし、次にマークされた文字をすべて削除し、 それがまだ の部分列で あるかどうかを 確認するというものです。skkps0 <= i < ks[removable[i]]ps

文字を削除した後も存在する、 確認できる 最大のサブシーケンスを返します 。 k  p s

文字列の サブシーケンス は、元の文字列から生成された新しい文字列であり、元の文字列から一部の文字が削除される場合と削除されない場合がありますが、残りの文字の相対的な順序は変更されません。

例 1:

入力: s = "abcacb"、p = "ab"、リムーバブル = [3,1,0]
出力: 2
説明:添字 3 と 1 に対応する文字を削除すると、「ab c a cb」は「accb」になります。 。
「ab」は「 a cc b 」の部分列です。
添え字 3、1、および 0 に対応する文字を削除した後、 「 ab c a cb」が「ccb」になる場合、「ab」は s の部分列ではなくなります。
したがって、最大の k は 2 になります。

例 2:

入力: s = "abcbddddd"、p = "abcd"、リムーバブル = [3,2,1,4,5,6]
出力: 1
説明:添え字 3 に対応する文字を削除すると、「abc b ddddd」は " になります。 ABCDDDD」。
「abcd」は「 abcd dddd」のサブシーケンス
です。

例 3:

入力: s = "abcab"、p = "abc"、removable = [0,1,2,3,4]
出力: 0
説明: removable 配列の最初の添え字が削除されると、「abc」は存在しなくなります。 s の部分列。

ヒント:

  • 1 <= p.length <= s.length <= 105
  • 0 <= removable.length < s.length
  • 0 <= removable[i] < s.length
  • p部分文字s 列  です 
  • s どちら p も英小文字で構成されています
  • removable の要素は 互いに異なります

パス数: 5,532 提出数: 16,167

解決策: 最小削除数は 0 で、最大削除数は です。removable.length,针对这个移除个数来进行二分查找,每次到mid的时候,都需要将mid之前的字符去掉,然后判断s是不是t的母字符串,如果是继续向后查找,如果不是二分向前查找。

具体代码如下:

class Solution {
    bool isSubsequence(string s, string t) 
    {
        // 判断s是否为t的子序列
        int n = s.size(), m = t.size();
        int i = 0, j = 0;
        while(i<n && j<m){
            if(s[i] == t[j]){
                i++;
                j++;
            }else{
                j++;
            }
        }
        return i==n;
    }
public:
    int maximumRemovals(string s, string p, vector<int>& removable) {
        int i=0;
        int left=0,right=removable.size();
        while(left<right)
        {
            int mid=left+(right-left)/2;
            string ss=s;
            for(i=0;i<=mid;i++)
            {
                ss[removable[i]]='#';
            }
            if(isSubsequence(p,ss))
            {
                left=mid+1;
            }
            else
            {
                right=mid;
            }
        }
        return left;
    }
};

結果:

合格

詳細を表示

メモを追加する

実行時間: 172 ミリ秒、すべての C++ 送信の 99.52% を上回りました

メモリ消費量: 119.3 MB、すべての C++ 送信のユーザーの 52.77% を上回ります

合格したテスト ケース: 67/67

おすすめ

転載: blog.csdn.net/weixin_41579872/article/details/124916700