LEETCODE-3。文字が繰り返されていない最長の部分文字列
タイトル-繰り返し文字のない最長の部分文字列
文字列を指定して、繰り返し文字を含まない最長の部分文字列の長さを見つけてください。
例1:
入力: "abcabcbb"
出力:3
説明:繰り返し文字のない最長のサブストリングは "abc"であるため、その長さは3です。
例2:
入力: "bbbbb"
出力:1
説明:繰り返し文字のない最長のサブストリングは "b"であるため、その長さは1です。
例3:
入力: "pwwkew"
出力:3
説明:繰り返し文字のない最長のサブストリングは "wke"であるため、その長さは3です。
答えは部分文字列の長さでなければならないことに注意してください。「pwke」は部分文字列ではなく部分列です。
ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/longest-substring-without-repeating-characters
方法1スライディングウィンドウ+ハッシュテーブル
直接2層ループトラバーサルの複雑さはO(n ^ 2)であるため、使用されませんが、ハッシュテーブルが使用されます。ハッシュテーブル信号の各要素のラベルは、要素とスペース文字の違いを示し、各要素の値は文字列内の位置を示します。たとえば、文字列abbacbでは、文字 'c'が4桁目(0から数えて)に表示され、そのハッシュ値はc- '' = 99-32 = 67であり、信号[67] = 4を設定します。ここでのテーブルのサイズは個人的な癖の問題であり、ASCIIコードが0であるヌル文字で開始することもできます。
最初に信号を初期化し、各要素を-1に初期化します。次に、入力文字列sを最初からトラバースし、シグナルテーブル内の現在の文字cのハッシュ値が-1の場合、それを文字列内のcの位置に変更します。signalの値が0以上の場合、要素が現在の部分文字列に出現したことを意味します。現在の部分文字列の長さを数え、それが以前の最大値を超えている場合は、最大値を更新します。トラバーサル位置をcの信号テーブルの要素値の位置に変更して、新しいサブストリングの検索を再開し、信号テーブルを空にして、前のプロセスを繰り返します。
int lengthOfLongestSubstring(char * s){
int signal[96] = {-1};
int longest_sub_length = 0;
int cur_sub_length = 0;
int cur_sub_position = 0;
int i = 0;
int j = 0;
memset(signal,-1,sizeof(signal));
while(s[i] != '\0')
{
if(signal[s[i]-' '] == -1) //当前字符未重复过
{
signal[s[i]-' '] = i;
i++;
cur_sub_length++;
continue;
}
else //当前字符是重复字符
{
longest_sub_length = cur_sub_length > longest_sub_length ? cur_sub_length : longest_sub_length;
cur_sub_position = signal[s[i]-' '] ;
cur_sub_length = 0;
for(j = 0; j < 95; j++)
signal[j] = -1;
i = cur_sub_position + 1;
}
}
longest_sub_length = cur_sub_length > longest_sub_length ? cur_sub_length : longest_sub_length;
return longest_sub_length;
}
方法2:スライディングウィンドウを最適化する
方法1には余分な部分があります。つまり、繰り返し文字がある場合、ハッシュテーブルをリセットする必要があります。以前にテーブルにあった要素は初期化され、これらの要素を繰り返し入力する必要があります。したがって、最適化は次のとおりです。
- 開始ポインタは、現在の部分文字列の開始位置を示します。ハッシュテーブルの構成は元のものと同じですが、要素に格納されている値は1から計算されます。
- トラバースされた現在の要素の位置を表します
- s [i]> startの場合、現在の走査された要素が現在の部分文字列の接頭辞に出現しているため、部分文字列の走査が終了し、部分文字列の長さが計算されます
- 最も重要な変更:繰り返し文字が表示される場合、現在の走査位置は前方にジャンプせず、部分文字列の開始位置が変更されている限り、後方に走査し続けます。
例:文字列「ilovelty」、最初の部分文字列の開始位置は0、2番目の「l」がトラバースされると、繰り返し条件が満たされ、文字列の最大長が更新され、部分文字列の開始位置がoに設定されます。開始位置は2です。トラバーサルの後、最長のサブストリングは「ovelty」であり、長さは6です。
int lengthOfLongestSubstring(char * s){
int i, j = 0, length = 0, max_length = 0, signal[128] = {0}, start = 0;
for(i=0;s[i]!='\0';i++)
{
if(signal[s[i]]>start)
{
length = i-start;
if(length>max_length)
{
max_length = length;
}
start = signal[s[i]];
}
signal[s[i]] = i+1;
}
length = i-start;
return length>max_length?length:max_length;
}
参考資料
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/cyu-yan-shuang-yi-bai-by-wu-sheng-23/