Likou 844.文字列をバックスペースと比較する--- 2つの方法(スタックとダブルポインタ)

844.文字列をバックスペースと比較する

SとTの2つの文字列が与えられた場合、それらが空白のテキストエディタに入力されると、それらが等しいかどうかを判断し、結果を返します。#バックスペース文字を表します。

注:空のテキストにバックスペース文字を入力すると、テキストは空のままになります。

例1:

入力:S = "ab#c"、T = "ad#c"
出力:true
説明:SとTの両方が "ac"になります。
例2:

入力:S = "ab ##"、T = "c#d#"
出力:true
説明:SとTの両方が ""になります。
例3:

入力:S = "a ## c"、T = "#a#c"
出力:true
説明:SとTの両方が "c"になります。
例4:

入力:S = "a#c"、T = "b"
出力:false
説明:Sは "c"になりますが、Tは "b"のままです。

提示:
1 <= S.length <= 200
1 <= T.length <= 200
S 和 T 只含有小写字母以及字符 '#'。
进阶:
你可以用 O(N) 的时间复杂度和 O(1) 的空间复杂度解决该问题吗?
 

回答:

方法1:スタック+文字列の再構築

バックスペースキーが存在するため、これらのバックスペースキーを使用するだけで実際の文字列を再構築できます。最後に、再編成後の2つが同じかどうかを比較します。

コード:

char*bj(char*str)//此为“重组”函数
{
    
    
    int n = strlen(str);
    char*temp=(char*)malloc((n+1)*sizeof(char));//用来临时储存“重组”后的字符串,先设置内存大点
    int len = 0;//此为代表“重组”后的字符串数组的下标,开始为0
    for(int i=0;i<n;i++)//for循环来填充
    {
    
    
        if(str[i]!='#')//如果不是退格键,则直接赋给他即可
        {
    
    
            temp[len]=str[i];
            len++;//下标先指向下一个
        }
        else if(len>0)//是退格键的情况,但前提须是“重组”后的字符串数组的下标须大于0
        	//因为进入此条件体内下面我们要对len--,所以len在进来时就必须先是>0的,不然会越界
        {
    
    
            len--;//因为是退格键,所以即相当于“删掉”了前一个,所以要对前一个进行重新赋值,所以下标往前一个
        }
    }
    temp[len]='\0';//因为开始不知道应该申请多大内存,而字符串数组以‘\0’为结尾
    			//所以先申请一个最大的,最后再“去掉”多余的即可
    return temp;
}
bool backspaceCompare(char * S, char * T){
    
    
    return strcmp(bj(S),bj(T))==0;//代入函数验证即可
}

この方法は効率が悪くなりますが、ロジックは単純です。

方法2:論理処理-ダブルポインター検索

この方法は非常に効率的ですが、論理的にはより複雑です。

最初に理解することは、ダブルポインターを使用し検索する場合、開始位置は最初または最後から検索する必要があるということです。
タイトルから、文字はその後に表示されるバックスペースキーによってのみ影響を受け、前に表示されるバックスペースキーは影響を受けないことがわかります。つまり、最初から検索する場合、#に遭遇した場合は、前のものを操作する必要があります。そして、最後から検索すると、#に出会ったら最初に保存します。#に出会わない場合は、保存されている#の数からこの時点の文字が削除されるかどうかをすぐに判断できます。ゼロから検索する場合、この手順を完了するのはより複雑であることがわかりました。

次のプロセスをよりよく理解するために、神の解決策の写真を添付し​​てください。
ここに画像の説明を挿入します

最後から検索を確認した後、最初にS配列を検索できます。この時点で対応する要素が#の場合は、#を1回格納し、ポインタを1回前方に移動します。#でない場合は、格納されている#がオフセットされているかどうかを確認します。終了します。オフセットが完了していない場合は、オフセットを1回実行すると、ポインタが再び前方に移動します。オフセットが完了した場合、この時点の文字は、バックスペースキーの処理後に存在するはずの実際の文字と同等であることを意味します。この時点で使用できます。同じ操作で取得した文字をT配列と比較して、等しいかどうかを確認します。

つまり上記の操作の目的は、バックスペース処理後にS配列とT配列から実際の文字を取り出して比較することです。

コードの詳細は次のとおりです。

----注:コード内でiとjの両方が負の場合、S [i]とT [j]が等しいかどうかを比較する必要はありません。なぜですか。
iとjが両方とも負の場合、バックスペースキー操作後に実際に存在した文字が選択されなかったことを意味します選択されいないため、問題ありません
もちろんiとjの両方選択されている可能性もあります。独自の配列をトラバースします。それで問題ありません。トラバースは完了しているので、比較する必要はありません。

注:最初のwhileループの条件が「i> = 0 || j> = 0」であるのはなぜですか?
ポインタは小さな配列であるためすばやく検索される可能性があるため、検索はすばやく完了します。したがって、この時点では、対応するiまたはjは負ですが、もう一方は遅く、検索を続けます。また、この状況は必ずしも「真」を意味するわけでも、必ずしも「偽」を意味するわけでもないためコンテンツ検索できないかどうかを確認するために、もう一度検証を実行する必要があります。検索できない場合は、「真」です。 ;そうでない場合、つまり、一方のコンテンツをもう一方コンテンツを検索した後に検索できる場合2つ異なっている必要があるため、「false」です。

そして、それが負の値でない場合、それは明確でなければなりません------ i、j、つまり、対応するS [i]、T [j]は#ではありません。 (これは、whileループ条件が原因で発生します)

コード:

bool backspaceCompare(char * S, char * T){
    
    
    int i=strlen(S)-1;//S的指针
    int j=strlen(T)-1;//T的指针
    int nums = 0;//S的计数器,存储S的#个数
    int numt = 0;//T的计数器,存储T的#个数
    while(i>=0||j>=0)//进入搜索查找循环
    {
    
    
        while(i>=0)//先查找出S的经过退格处理的真正存在的字符,因为i为S的查找指针,
        	//每一个都要查找,所以i=0也要查找,所以循环为i>=0就要进入循环
        {
    
    
            if(S[i]=='#')
            {
    
    
                nums++;
                i--;
                continue;
            }
            if(nums!=0)
            {
    
    
                i--;
                nums--;
                continue;
            }
            if(nums==0)
            {
    
    
                break;
            }
        }
        while(j>=0)//再找出T的经过退格处理的真正存在的字符,同理j>=0
        {
    
    
            if(T[j]=='#')
            {
    
    
                numt++;
                j--;
                continue;
            }
            if(numt!=0)
            {
    
    
                j--;
                numt--;
                continue;
            }
            if(numt==0)
            {
    
    
                break;
            }
        }
        if(i>=0&&j>=0)//首先满足i,j不越界,即都搜索到了内容时
        {
    
    
            if(S[i]!=T[j])//进行比较
                return 0;
        }
        else//else的条件其实就是当不满足前面的if条件时,所以即i,j有越界的,即有没有搜索到内容的
        {
    
    
            if(i >= 0 || j >= 0)//在else的情况下,所以必定有至少一个没有搜索到内容
            {
    
    //若是都没搜索到,则没啥事,若是一个搜索到了,一个没搜索到,则一定为“假”了
                return false;//因为搜索时本来就把退格键使用了,所以此时显然S与T不相同了
            }
        }
        i--;//移动指针
        j--;
    }
    return 1;
}

おすすめ

転載: blog.csdn.net/xiangguang_fight/article/details/112291205