Étant donné que string S
sur length N
, recherchez la plus longue sous-chaîne sans répéter les caractères.
Exemple:
Entrée: "stackoverflow"
Sortie: "stackoverfl"
S'il y a deux candidats de ce type, revenez d'abord par la gauche. J'ai besoin de temps linéaire et d'algorithme d'espace constant.
import Java.util.HashSet;
public class SubString {
public static String subString(String input){
HashSet<Character> set = new HashSet<Character>();
String longestOverAll = "";
String longestTillNow = "";
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (set.contains(c)) {
longestTillNow = "";
set.clear();
}
longestTillNow += c;
set.add(c);
if (longestTillNow.length() > longestOverAll.length()) {
longestOverAll = longestTillNow;
}
}
return longestOverAll;
}
public static void main(String[] args) {
String input = "substringfindout";
System.out.println(subString(input));
}
}
Vous conservez un tableau indiquant la position à laquelle un certain caractère est apparu en dernier. Par commodité, tous les caractères sont apparus à la position -1. Vous parcourez la chaîne en gardant une fenêtre, si un caractère est répété dans cette fenêtre, vous coupez le préfixe qui se termine par la première occurrence de ce caractère. Tout au long, vous maintenez la plus longue longueur. Voici une implémentation en python:
def longest_unique_substr(S):
# This should be replaced by an array (size = alphabet size).
last_occurrence = {}
longest_len_so_far = 0
longest_pos_so_far = 0
curr_starting_pos = 0
curr_length = 0
for k, c in enumerate(S):
l = last_occurrence.get(c, -1)
# If no repetition within window, no problems.
if l < curr_starting_pos:
curr_length += 1
else:
# Check if it is the longest so far
if curr_length > longest_len_so_far:
longest_pos_so_far = curr_starting_pos
longest_len_so_far = curr_length
# Cut the prefix that has repetition
curr_length -= l - curr_starting_pos
curr_starting_pos = l + 1
# In any case, update last_occurrence
last_occurrence[c] = k
# Maybe the longest substring is a suffix
if curr_length > longest_len_so_far:
longest_pos_so_far = curr_starting_pos
longest_len_so_far = curr_length
return S[longest_pos_so_far:longest_pos_so_far + longest_len_so_far]
ÉDITÉ:
voici une mise en œuvre du concesus. Cela m'est arrivé après ma publication originale. afin de ne pas supprimer l'original, il est présenté comme suit:
public static String longestUniqueString(String S) {
int start = 0, end = 0, length = 0;
boolean bits[] = new boolean[256];
int x = 0, y = 0;
for (; x < S.length() && y < S.length() && length < S.length() - x; x++) {
bits[S.charAt(x)] = true;
for (y++; y < S.length() && !bits[S.charAt(y)]; y++) {
bits[S.charAt(y)] = true;
}
if (length < y - x) {
start = x;
end = y;
length = y - x;
}
while(y<S.length() && x<y && S.charAt(x) != S.charAt(y))
bits[S.charAt(x++)]=false;
}
return S.substring(start, end);
}//
POSTE ORIGINAL:
Voici mes deux cents. Cordes de test incluses. boolean bits [] = new boolean [256] peut être plus grand pour englober un jeu de caractères plus grand.
public static String longestUniqueString(String S) {
int start=0, end=0, length=0;
boolean bits[] = new boolean[256];
int x=0, y=0;
for(;x<S.length() && y<S.length() && length < S.length()-x;x++) {
Arrays.fill(bits, false);
bits[S.charAt(x)]=true;
for(y=x+1;y<S.length() && !bits[S.charAt(y)];y++) {
bits[S.charAt(y)]=true;
}
if(length<y-x) {
start=x;
end=y;
length=y-x;
}
}
return S.substring(start,end);
}//
public static void main(String... args) {
String input[][] = { { "" }, { "a" }, { "ab" }, { "aab" }, { "abb" },
{ "aabc" }, { "abbc" }, { "aabbccdefgbc" },
{ "abcdeafghicabcdefghijklmnop" },
{ "abcdeafghicabcdefghijklmnopqrabcdx" },
{ "zxxaabcdeafghicabcdefghijklmnopqrabcdx" },
{"aaabcdefgaaa"}};
for (String[] a : input) {
System.out.format("%s *** GIVES *** {%s}%n", Arrays.toString(a),
longestUniqueString(a[0]));
}
}
Voici une solution supplémentaire avec seulement 2 variables de chaîne:
public static String getLongestNonRepeatingString(String inputStr){
if(inputStr == null){
return null;
}
String maxStr = "";
String tempStr = "";
for(int i=0; i < inputStr.length(); i++){
// 1. if tempStr contains new character, then change tempStr
if(tempStr.contains("" + inputStr.charAt(i))){
tempStr = tempStr.substring(tempStr.lastIndexOf(inputStr.charAt(i)) + 1);
}
// 2. add new character
tempStr = tempStr + inputStr.charAt(i);
// 3. replace maxStr with tempStr if tempStr is longer
if(maxStr.length() < tempStr.length()){
maxStr = tempStr;
}
}
return maxStr;
}
Une autre solution O(n) JavaScript. Il ne modifie pas les chaînes pendant le bouclage; il garde juste trace du décalage et de la longueur de la plus longue chaîne secondaire jusqu'à présent:
function longest(str) {
var hash = {}, start, end, bestStart, best;
start = end = bestStart = best = 0;
while (end < str.length) {
while (hash[str[end]]) hash[str[start++]] = 0;
hash[str[end]] = 1;
if (++end - start > best) bestStart = start, best = end - start;
}
return str.substr(bestStart, best);
}
// I/O for snippet
document.querySelector('input').addEventListener('input', function () {
document.querySelector('span').textContent = longest(this.value);
});
Enter Word:<input><br>
Longest: <span></span>
Nous pouvons examiner toutes les sous-chaînes une par une et vérifier pour chaque sous-chaîne si elle contient ou non tous les caractères uniques. Il y aura n * (n + 1)/2 sous-chaînes. Si un substitut contient tous les caractères uniques ou non, peut être vérifié en temps linéaire par le scanner de gauche à droite et en gardant une carte des personnages visités. La complexité temporelle de cette solution serait O (n ^ 3). »
import Java.util.ArrayList;
import Java.util.Collections;
import Java.util.HashMap;
import Java.util.LinkedHashSet;
import Java.util.List;
import Java.util.Map;
import Java.util.Set;
public class LengthOfLongestSubstringWithOutRepeatingChar {
public static void main(String[] args)
{
String s="stackoverflow";
//allSubString(s);
System.out.println("result of find"+find(s));
}
public static String find(String s)
{
List<String> allSubsring=allSubString(s);
Set<String> main =new LinkedHashSet<String>();
for(String temp:allSubsring)
{
boolean a = false;
for(int i=0;i<temp.length();i++)
{
for(int k=temp.length()-1;k>i;k--)
{
if(temp.charAt(k)==temp.charAt(i))
a=true;
}
}
if(!a)
{
main.add(temp);
}
}
/*for(String x:main)
{
System.out.println(x);
}*/
String res=null;
int min=0,max=s.length();
for(String temp:main)
{
if(temp.length()>min&&temp.length()<max)
{
min=temp.length();
res=temp;
}
}
System.out.println(min+"ha ha ha"+res+"he he he");
return res;
}
//substrings left to right ban rahi hai
private static List<String> allSubString(String str) {
List<String> all=new ArrayList<String>();
int c=0;
for (int i = 0; i < str.length(); i++) {
for (int j = 0; j <= i; j++) {
if (!all.contains(str.substring(j, i + 1)))
{
c++;
all.add(str.substring(j, i + 1));
}
}
}
for(String temp:all)
{
System.out.println("substring :-"+temp);
}
System.out.println("count"+c);
return all;
}
}
Algorithme en JavaScript (avec beaucoup de commentaires) ..
/**
Given a string S find longest substring without repeating characters.
Example:
Input: "stackoverflow"
Output: "stackoverfl"
Input: "stackoverflowabcdefghijklmn"
Output: "owabcdefghijklmn"
*/
function findLongestNonRepeatingSubStr(input) {
var chars = input.split('');
var currChar;
var str = "";
var longestStr = "";
var hash = {};
for (var i = 0; i < chars.length; i++) {
currChar = chars[i];
if (!hash[chars[i]]) { // if hash doesn't have the char,
str += currChar; //add it to str
hash[chars[i]] = {index:i};//store the index of the char
} else {// if a duplicate char found..
//store the current longest non-repeating chars. until now
//In case of equal-length, <= right-most str, < will result in left most str
if(longestStr.length <= str.length) {
longestStr = str;
}
//Get the previous duplicate char's index
var prevDupeIndex = hash[currChar].index;
//Find all the chars AFTER previous duplicate char and current one
var strFromPrevDupe = input.substring(prevDupeIndex + 1, i);
//*NEW* longest string will be chars AFTER prevDupe till current char
str = strFromPrevDupe + currChar;
//console.log(str);
//Also, Reset hash to letters AFTER duplicate letter till current char
hash = {};
for (var j = prevDupeIndex + 1; j <= i; j++) {
hash[input.charAt(j)] = {index:j};
}
}
}
return longestStr.length > str.length ? longestStr : str;
}
//console.log("stackoverflow => " + findLongestNonRepeatingSubStr("stackoverflow"));
//returns stackoverfl
//console.log("stackoverflowabcdefghijklmn => " +
findLongestNonRepeatingSubStr("stackoverflowabcdefghijklmn")); //returns owabcdefghijklmn
//console.log("1230123450101 => " + findLongestNonRepeatingSubStr("1230123450101")); //
returns 234501
import Java.util.HashMap;
import Java.util.HashSet;
public class SubString {
public static String subString(String input) {
String longesTillNOw = "";
String longestOverAll = "";
HashMap<Character,Integer> chars = new HashMap<>();
char[] array=input.toCharArray();
int start=0;
for (int i = 0; i < array.length; i++) {
char charactor = array[i];
if (chars.containsKey(charactor) ) {
start=chars.get(charactor)+1;
i=start;
chars.clear();
longesTillNOw = "";
} else {
chars.put(charactor,i);
longesTillNOw = longesTillNOw + charactor;
if (longesTillNOw.length() > longestOverAll.length()) {
longestOverAll = longesTillNOw;
}
}
}
return longestOverAll;
}
public static void main(String[] args) {
String input = "stackoverflowabcdefghijklmn";
System.out.println(subString(input));
}
}
Question: Trouvez la plus longue sous-chaîne sans répéter les caractères ..___ Exemple 1:
import Java.util.LinkedHashMap;
import Java.util.Map;
public class example1 {
public static void main(String[] args) {
String a = "abcabcbb";
// output => 3
System.out.println( lengthOfLongestSubstring(a));
}
private static int lengthOfLongestSubstring(String a) {
if(a == null || a.length() == 0) {return 0 ;}
int res = 0 ;
Map<Character , Integer> map = new LinkedHashMap<>();
for (int i = 0; i < a.length(); i++) {
char ch = a.charAt(i);
if (!map.containsKey(ch)) {
//If ch is not present in map, adding ch into map along with its position
map.put(ch, i);
}else {
/*
If char ch is present in Map, reposition the cursor i to the position of ch and clear the Map.
*/
i = map.put(ch, i);// updation of index
map.clear();
}//else
res = Math.max(res, map.size());
}
return res;
}
}
si vous voulez la sortie de la chaîne la plus longue sans les caractères répétés, faites-le dans la boucle for:
String res ="";// global
int len = 0 ;//global
if(len < map.size()) {
len = map.size();
res = map.keySet().toString();
}
System.out.println("len -> " + len);
System.out.println("res => " + res);
Ceci est ma solution, et cela a été accepté par leetcode. Cependant, après avoir vu les statistiques, j'ai constaté que le résultat final était beaucoup plus rapide…. Cela signifie que ma solution est d'environ 600 ms pour tous les tests, et que la plupart des solutions js se situent entre 200 et 300 ms. peut me dire pourquoi ma solution est lentewww ??
var lengthOfLongestSubstring = function(s) {
var arr = s.split("");
if (s.length === 0 || s.length === 1) {
return s.length;
}
var head = 0,
tail = 1;
var str = arr[head];
var maxL = 0;
while (tail < arr.length) {
if (str.indexOf(arr[tail]) == -1) {
str += arr[tail];
maxL = Math.max(maxL, str.length);
tail++;
} else {
maxL = Math.max(maxL, str.length);
head = head + str.indexOf(arr[tail]) + 1;
str = arr[head];
tail = head + 1;
}
}
return maxL;
};
import Java.util.ArrayList;
import Java.util.HashSet;
import Java.util.LinkedHashSet;
import Java.util.List;
import Java.util.Set;
import Java.util.TreeMap;
public class LongestSubString2 {
public static void main(String[] args) {
String input = "stackoverflowabcdefghijklmn";
List<String> allOutPuts = new ArrayList<String>();
TreeMap<Integer, Set> map = new TreeMap<Integer, Set>();
for (int k = 0; k < input.length(); k++) {
String input1 = input.substring(k);
String longestSubString = getLongestSubString(input1);
allOutPuts.add(longestSubString);
}
for (String str : allOutPuts) {
int strLen = str.length();
if (map.containsKey(strLen)) {
Set set2 = (HashSet) map.get(strLen);
set2.add(str);
map.put(strLen, set2);
} else {
Set set1 = new HashSet();
set1.add(str);
map.put(strLen, set1);
}
}
System.out.println(map.lastKey());
System.out.println(map.get(map.lastKey()));
}
private static void printArray(Object[] currentObjArr) {
for (Object obj : currentObjArr) {
char str = (char) obj;
System.out.println(str);
}
}
private static String getLongestSubString(String input) {
Set<Character> set = new LinkedHashSet<Character>();
String longestString = "";
int len = input.length();
for (int i = 0; i < len; i++) {
char currentChar = input.charAt(i);
boolean isCharAdded = set.add(currentChar);
if (isCharAdded) {
if (i == len - 1) {
String currentStr = getStringFromSet(set);
if (currentStr.length() > longestString.length()) {
longestString = currentStr;
}
}
continue;
} else {
String currentStr = getStringFromSet(set);
if (currentStr.length() > longestString.length()) {
longestString = currentStr;
}
set = new LinkedHashSet<Character>(input.charAt(i));
}
}
return longestString;
}
private static String getStringFromSet(Set<Character> set) {
Object[] charArr = set.toArray();
StringBuffer strBuff = new StringBuffer();
for (Object obj : charArr) {
strBuff.append(obj);
}
return strBuff.toString();
}
}
def max_substring(string):
last_substring = ''
max_substring = ''
for x in string:
k = find_index(x,last_substring)
last_substring = last_substring[(k+1):]+x
if len(last_substring) > len(max_substring):
max_substring = last_substring
return max_substring
def find_index(x, lst):
k = 0
while k <len(lst):
if lst[k] == x:
return k
k +=1
return -1
function longestSubstringWithoutDuplication(str) {
var max = 0;
//if empty string
if (str.length === 0){
return 0;
} else if (str.length === 1){ //case if the string's length is 1
return 1;
}
//loop over all the chars in the strings
var currentChar,
map = {},
counter = 0; //count the number of char in each substring without duplications
for (var i=0; i< str.length ; i++){
currentChar = str.charAt(i);
//if the current char is not in the map
if (map[currentChar] == undefined){
//Push the currentChar to the map
map[currentChar] = i;
if (Object.keys(map).length > max){
max = Object.keys(map).length;
}
} else { //there is duplacation
//update the max
if (Object.keys(map).length > max){
max = Object.keys(map).length;
}
counter = 0; //initilize the counter to count next substring
i = map[currentChar]; //start from the duplicated char
map = {}; // clean the map
}
}
return max;
}
La solution en C.
#include<stdio.h>
#include <string.h>
void longstr(char* a, int *start, int *last)
{
*start = *last = 0;
int visited[256];
for (int i = 0; i < 256; i++)
{
visited[i] = -1;
}
int max_len = 0;
int cur_len = 0;
int prev_index;
visited[a[0]] = 0;
for (int i = 1; i < strlen(a); i++)
{
prev_index = visited[a[i]];
if (prev_index == -1 || i - cur_len > prev_index)
{
cur_len++;
*last = i;
}
else
{
if (max_len < cur_len)
{
*start = *last - cur_len;
max_len = cur_len;
}
cur_len = i - prev_index;
}
visited[a[i]] = i;
}
if (max_len < cur_len)
{
*start = *last - cur_len;
max_len = cur_len;
}
}
int main()
{
char str[] = "ABDEFGABEF";
printf("The input string is %s \n", str);
int start, last;
longstr(str, &start, &last);
//printf("\n %d %d \n", start, last);
memmove(str, (str + start), last - start);
str[last] = '\0';
printf("the longest non-repeating character substring is %s", str);
return 0;
}
pouvons-nous utiliser quelque chose comme ça.
def longestpalindrome(str1):
arr1=list(str1)
s=set(arr1)
arr2=list(s)
return len(arr2)
str1='abadef'
a=longestpalindrome(str1)
print(a)
si seule la longueur de la sous-chaîne doit être renvoyée
J'ai modifié ma solution pour "trouver la longueur de la plus longue sous-chaîne sans répéter les caractères".
public string LengthOfLongestSubstring(string s) {
var res = 0;
var dict = new Dictionary<char, int>();
var start = 0;
for(int i =0; i< s.Length; i++)
{
if(dict.ContainsKey(s[i]))
{
start = Math.Max(start, dict[s[i]] + 1); //update start index
dict[s[i]] = i;
}
else
{
dict.Add(s[i], i);
}
res = Math.Max(res, i - start + 1); //track max length
}
return s.Substring(start,res);
}
Voici deux manières d'aborder ce problème en JavaScript.
Une approche Brute Force consiste à parcourir la chaîne deux fois, en comparant chaque sous-chaîne à une autre et en recherchant la longueur maximale lorsque la sous-chaîne est unique. Nous aurons besoin de deux fonctions: une pour vérifier si une sous-chaîne est unique et une seconde pour effectuer notre double boucle.
// O(n) time
const allUnique = str => {
const set = [...new Set(str)];
return (set.length == str.length) ? true: false;
}
// O(n^3) time, O(k) size where k is the size of the set
const lengthOfLongestSubstring = str => {
let result = 0,
maxResult = 0;
for (let i=0; i<str.length-1; i++) {
for (let j=i+1; j<str.length; j++) {
if (allUnique(str.substring(i, j))) {
result = str.substring(i, j).length;
if (result > maxResult) {
maxResult = result;
}
}
}
return maxResult;
}
}
Cela a une complexité temporelle de O(n^3)
puisque nous effectuons une double boucle O(n^2)
, puis une autre boucle au-dessus de cette O(n)
pour notre fonction unique. L'espace est la taille de notre ensemble qui peut être généralisé à O(n)
ou plus précisément O(k)
où k
est la taille de l'ensemble.
Une approche Greedy consiste à effectuer une boucle unique et à suivre la longueur maximale de la sous-chaîne au fur et à mesure. Nous pouvons utiliser un tableau ou une carte de hachage, mais je pense que la nouvelle méthode .includes () array est cool, alors utilisons-la.
const lengthOfLongestSubstring = str => {
let result = [],
maxResult = 0;
for (let i=0; i<str.length; i++) {
if (!result.includes(str[i])) {
result.Push(str[i]);
} else {
maxResult = i;
}
}
return maxResult;
}
Cela a une complexité temporelle de O(n)
et une complexité d'espace de O(1)
.
Pas tout à fait optimisé mais réponse simple en Python
def lengthOfLongestSubstring(s):
temp,maxlen,newstart = {},0,0
for i,x in enumerate(s):
if x in temp:
newstart = max(newstart,s[:i].rfind(x)+1)
else:
temp[x] = 1
maxlen = max(maxlen, len(s[newstart:i + 1]))
return maxlen
Je pense que l'affaire coûteuse est rfind
, c'est pourquoi elle n'est pas tout à fait optimisée.
Testé et fonctionnel. Pour faciliter la compréhension, je suppose qu’il existe un tiroir pour mettre les lettres.
public int lengthOfLongestSubstring(String s) {
int maxlen = 0;
int start = 0;
int end = 0;
HashSet<Character> drawer = new HashSet<Character>();
for (int i=0; i<s.length(); i++) {
char ch = s.charAt(i);
if (drawer.contains(ch)) {
//search for ch between start and end
while (s.charAt(start)!=ch) {
//drop letter from drawer
drawer.remove(s.charAt(start));
start++;
}
//Do not remove from drawer actual char (it's the new recently found)
start++;
end++;
}
else {
drawer.add(ch);
end++;
int _maxlen = end-start;
if (_maxlen>maxlen) {
maxlen=_maxlen;
}
}
}
return maxlen;
}
Algorithme:
1) Initialisez un dictionnaire vide-dct pour vérifier si un caractère existe déjà dans la chaîne.
2) cnt - pour conserver le nombre de sous-chaînes sans répéter les caractères.
3) l et r sont les deux pointeurs initialisés au premier index de la chaîne.
4) boucle à travers chaque caractère de la chaîne.
5) Si le caractère non présent dans le dct ajoutez-le et augmentez le cnt .
6) S'il est déjà présent, vérifiez si cnt est supérieur à resStrLen .
7) Retirez le caractère de dct et déplacez le pointeur gauche de 1 et diminuez le compte.
8) Répétez 5,6,7 jusqu'à l , r supérieur ou égal à la longueur de la chaîne d'entrée.
9) Faites un dernier contrôle à la fin pour traiter les cas tels que la chaîne de saisie avec des caractères non répétitifs.
Voici le programme simple python pour Trouver la plus longue sous-chaîne sans répéter les caractères
a="stackoverflow"
strLength = len(a)
dct={}
resStrLen=0
cnt=0
l=0
r=0
strb=l
stre=l
while(l<strLength and r<strLength):
if a[l] in dct:
if cnt>resStrLen:
resStrLen=cnt
strb=r
stre=l
dct.pop(a[r])
cnt=cnt-1
r+=1
else:
cnt+=1
dct[a[l]]=1
l+=1
if cnt>resStrLen:
resStrLen=cnt
strb=r
stre=l
print "Result String Length : "+str(resStrLen)
print "Result String : " + a[strb:stre]
Ce problème peut être résolu en O(n) complexité temporelle . Initialiser trois variables
Étapes: Parcourez la chaîne et effectuez les actions suivantes.
Si le caractère actuel est présent dans hashmap, alors
a) Vérifiez si l'index de départ est inférieur ou égal à la valeur présente dans la table de hachage par rapport au caractère (dernier index du même caractère précédemment visité),
b) il est inférieur à la valeur initiale des variables de démarrage en tant que valeur hashmaps + 1 (dernier index du même caractère précédemment visité + 1);
c) Mettez à jour hashmap en remplaçant la valeur du caractère actuel du hashmap par son index actuel.
d) Calculez le début de la fin comme la plus longue valeur de sous-chaîne et mettez-la à jour si elle est supérieure à la plus longue sous-chaîne la plus longue précédente.
Voici la solution Javascript pour résoudre ce problème.
var lengthOfLongestSubstring = function(s) {
let length = s.length;
let ans = 0;
let start = 0,
end = 0;
let hashMap = {};
for (var i = 0; i < length; i++) {
if (!hashMap.hasOwnProperty(s[i])) {
hashMap[s[i]] = i;
} else {
if (start <= hashMap[s[i]]) {
start = hashMap[s[i]] + 1;
}
hashMap[s[i]] = i;
}
end++;
ans = ans > (end - start) ? ans : (end - start);
}
return ans;
};
Simple et facile
import Java.util.Scanner;
public class longestsub {
static Scanner sn = new Scanner(System.in);
static String Word = sn.nextLine();
public static void main(String[] args) {
System.out.println("The Length is " +check(Word));
}
private static int check(String Word) {
String store="";
for (int i = 0; i < Word.length(); i++) {
if (store.indexOf(Word.charAt(i))<0) {
store = store+Word.charAt(i);
}
}
System.out.println("Result Word " +store);
return store.length();
}
}
Je poste O (n ^ 2) en python. Je veux juste savoir si la technique mentionnée par Karoly Horvath comporte des étapes similaires aux algorithmes de recherche/tri existants?
Mon code:
def main():
test='stackoverflow'
tempstr=''
maxlen,index=0,0
indexsubstring=''
print 'Original string is =%s\n\n' %test
while(index!=len(test)):
for char in test[index:]:
if char not in tempstr:
tempstr+=char
if len(tempstr)> len(indexsubstring):
indexsubstring=tempstr
Elif (len(tempstr)>=maxlen):
maxlen=len(tempstr)
indexsubstring=tempstr
break
tempstr=''
print 'max substring length till iteration with starting index =%s is %s'%(test[index],indexsubstring)
index+=1
if __name__=='__main__':
main()
voici mes implémentations javascript et cpp avec beaucoup de détails: https://algorithm.pingzhang.io/String/longest_substring_without_repeating_characters.html
Nous voulons trouver la plus longue sous-chaîne sans répéter les caractères. La première chose qui me vient à l’esprit est qu’il nous faut une table de hachage pour stocker chaque caractère dans une sous-chaîne, de sorte que lorsqu’un nouveau caractère entre, nous pouvons facilement savoir si ce caractère est déjà dans la sous-chaîne ou non. Je l'appelle comme valueIdxHash
. Ensuite, une sous-chaîne a startIdx
et endIdx
. Nous avons donc besoin d’une variable pour suivre l’index de départ d’une sous-chaîne et je l’appelle startIdx
. Supposons que nous sommes à index i
et que nous avons déjà une sous-chaîne (startIdx, i - 1)
. Maintenant, nous voulons vérifier si cette sous-chaîne peut continuer à croître ou non.
Si valueIdxHash
contientstr[i]
, cela signifie qu'il s'agit d'un caractère répété. Mais il reste à vérifier si ce caractère répété est dans la sous-chaîne (startIdx, i - 1)
. Nous devons donc récupérer l'index de str[i]
qui est apparu la dernière fois, puis comparer cet index avec startIdx
.
startIdx
est plus grand, cela signifie que le dernier str[i]
apparu est en dehors de de la sous-chaîne. Ainsi, la soustraction peut continuer à croître. startIdx
est plus petit, cela signifie que le dernier str[i]
apparu est dans de la sous-chaîne. Ainsi, la sous-chaîne ne peut plus grandir. startIdx
sera mis à jour en tant que valueIdxHash[str[i]] + 1
et la nouvelle sous-chaîne (valueIdxHash[str[i]] + 1, i)
a le potentiel de continuer à croître.Si la valueIdxHash
ne contient passtr[i]
, la sous-chaîne peut continuer à croître.