Найти самую длинную подстроку без повторяющихся символов - программирование
Подтвердить что ты не робот

Найти самую длинную подстроку без повторяющихся символов

Учитывая string S of length N найти самую длинную подстроку без повторяющихся символов.

Пример:

Вход: "stackoverflow"

Выход: "stackoverfl"

Если есть два таких кандидата, вернитесь сначала слева. Мне нужен алгоритм линейного времени и постоянного пространства.

4b9b3361

Ответ 1

  1. Вам понадобится начальный и конечный локатор (/указатель) для строки и массив, в котором вы храните информацию для каждого символа: произошло ли это хотя бы один раз?

  2. Начните с начала строки, оба локатора указывают на начало строки.

  3. Перемещайте указатель конца вправо, пока не найдете повтор (или не достигните конца строки). Для каждого обработанного символа сохраните его в массиве. Когда остановлено, сохраните позицию, если это самая большая подстрока. Также помните повторный характер.

  4. Теперь сделайте то же самое с локатором запуска, при обработке каждого символа удалите его флаги из массива. Перемещайте локатор, пока не найдете более раннее вхождение повторяющегося символа.

  5. Вернитесь к шагу 3, если вы еще не достигли конца строки.

Всего: O (N)

Ответ 2

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));
    }
}

Ответ 3

Вы сохраняете массив, указывающий позицию, в которой произошел последний символ. Для удобства все символы имели место в позиции -1. Вы повторяете строку, содержащую окно, если символ повторяется в этом окне, вы прерываете префикс, который заканчивается первым вхождением этого символа. Всюду вы сохраняете самую длинную длину. Здесь реализована реализация 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]

Ответ 4

Редакция:

следующая - реализация concesus. Это произошло со мной после моей первоначальной публикации. чтобы не удалять оригинал, он представлен ниже:

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);
}//

ОРИГИНАЛЬНАЯ ПОЧТА:

Вот мои два цента. Включены тестовые строки. boolean bits [] = new boolean [256] может быть больше, чтобы охватить некоторые более крупные кодировки.

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]));
    }
}

Ответ 5

Вот еще одно решение с двумя строковыми переменными:

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;
}

Ответ 6

Алгоритм в JavaScript (с большим количеством комментариев)..

/**
 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 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

Ответ 7

Мы можем рассматривать все подстроки один за другим и проверять каждую подстроку, содержит ли она все уникальные символы или нет. Будут n * (n + 1)/2 подстроки. Может ли подстановка содержать все уникальные символы или нет, можно проверить в линейном времени на сканирование слева направо и сохранение карты посещаемых символов. Временной сложностью этого решения было бы 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;
}
}

Ответ 8

Другое решение O (n) JavaScript. Он не изменяет строки во время цикла; он просто отслеживает смещение и длину самой длинной подстроки до сих пор:

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>

Ответ 9

введите описание изображения здесь простой фрагмент питона l = длина p = позиция maxl = maxlength maxp = maxposition

Ответ 10

I was asked the same question in an interview.

Я написал код Python 3, чтобы найти первое вхождение подстроки со всеми различными символами. В моих реализациях я начинаю с index = 0 и перебираю входную строку. Во время итерации использовали Python dict seems для хранения индексов символов во входной строке, которые были посещены в итерации.

В итерации, если char c, не находит в текущей подстроке & ndash; вызвать исключение KeyError

если c обнаружил дублирующийся символ в текущей подстроке (как c ранее появлялся во время итерации - назвал этот индекс last_seen), запустите новую подстроку

def lds(string: str) -> str:
    """ returns first longest distinct substring in input 'string' """
    seens = {}
    start, end, curt_start = 0, 0, 0
    for curt_end, c in enumerate(string):
        try:
            last_seen = seens[c]
            if last_seen < curt_start:
                raise KeyError(f"{c!r} not found in {string[curt_start: curt_end]!r}")
            if end - start <  curt_end - curt_start:
                start, end = curt_start, curt_end
            curt_start = last_seen + 1
        except KeyError:
            pass
        seens[c] = curt_end
    else: 
        # case when the longest substring is suffix of the string, here curt_end
        # do not point to a repeating char hance included in the substring
        if string and end - start <  curt_end - curt_start + 1:
            start, end = curt_start, curt_end + 1
    return string[start: end]

Ответ 11

Самая длинная подстрока без повторяющихся символов в питоне

public int lengthOfLongestSubstring(String s) {
    if(s.equals(""))
        return 0;
    String[] arr = s.split("");
    HashMap<String,Integer> map = new HashMap<>();
    Queue<String> q = new LinkedList<>();

    int l_till = 1;
    int l_all = 1;
    map.put(arr[0],0);
    q.add(arr[0]);
    for(int i = 1; i < s.length(); i++){
        if (map.containsKey(arr[i])) {
            if(l_till > l_all){
                l_all = l_till;
            }
            while(!q.isEmpty() && !q.peek().equals(arr[i])){
                map.remove(q.remove());
            }
            if(!q.isEmpty())
               map.remove(q.remove());
            q.add(arr[i]);
            map.put(arr[i],i);
            //System.out.println(q);
            //System.out.println(map);
            l_till = q.size();
        }
        else {
            l_till = l_till + 1;
            map.put(arr[i],i);
            q.add(arr[i]);
        }
    }
    if(l_till > l_all){
                l_all = l_till;
            }
    return l_all;
}

Ответ 12

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();
    }
}

Ответ 13

Это мое решение, и оно было принято с помощью leetcode. Тем не менее, после того, как я увидел статистику, я увидел, что решения с множеством решений имеют гораздо более быстрый результат... что означает, что мое решение составляет около 600 мс для всех их тестовых случаев, и большинство решений js составляют около 200-300 мкс. может сказать мне, почему мое решение работает медленно?

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;
};

Ответ 14

Я отправляю O (n ^ 2) в python. Я просто хочу знать, имеет ли метод, упомянутый Кароли Хорватом, какие-либо шаги, похожие на существующие алгоритмы поиска/сортировки?

Мой код:

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()

Ответ 15

Просто и легко

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();
    }

}

Ответ 16

Не совсем оптимизированный, но простой ответ в 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

Я думаю, что дорогостоящее дело rfind, поэтому оно не совсем оптимизировано.

Ответ 17

Проверено и работает. Для легкого понимания, я полагаю, там есть ящик для писем.

Функция:


    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 the new recently found)
                start++;
                end++;
            }
            else {
                drawer.add(ch);
                end++;
                int _maxlen = end-start;
                if (_maxlen>maxlen) {
                    maxlen=_maxlen;
                }
            }
        }
        return maxlen;
    }

Ответ 18

Это мое решение. Надеюсь, что это поможет.

  function longestSubstringWithoutDuplication(str) {
      var max = 0;

      //if empty string
      if (str.length === 0){
        return 0;
      } else if (str.length === 1){ //case if the string 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;
    }

Ответ 19

вот мои javascript и cpp-реализации с большими деталями: https://algorithm.pingzhang.io/String/longest_substring_without_repeating_characters.html

Мы хотим найти самую длинную подстроку без повторяющихся символов. Первое, что приходит мне в голову, это то, что нам нужна хеш-таблица для хранения каждого символа в подстроке, чтобы при входе нового персонажа мы можем легко узнать, находится ли этот символ уже в подстроке или нет. Я называю это valueIdxHash. Тогда подстрока имеет startIdx и endIdx. Поэтому нам нужна переменная, чтобы отслеживать начальный индекс подстроки, и я называю ее startIdx. Предположим, что мы находимся в индексе i, и у нас уже есть подстрока (startIdx, i - 1). Теперь мы хотим проверить, может ли эта подстрока продолжать расти или нет.

Если valueIdxHash содержит str[i], это означает, что это повторяющийся символ. Но нам все равно нужно проверить, находится ли этот повторяющийся символ в подстроке (startIdx, i - 1). Поэтому нам нужно получить индекс str[i], который появился в последний раз, а затем сравнить этот индекс с startIdx.

  • Если startIdx больше, это означает, что последний появился str[i] вне подстроки. Таким образом, подстрока может продолжать расти.
  • Если startIdx меньше, это означает, что последнее появилось str[i] внутри подстроки. Таким образом, подстрока больше не может расти. startIdx будет обновляться как valueIdxHash[str[i]] + 1, и новая подстрока (valueIdxHash[str[i]] + 1, i) может продолжать расти.

Если valueIdxHash не содержит str[i], подстрока может продолжать расти.

Ответ 20

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));
    }
}

Ответ 21

Я изменил свое решение, чтобы "найти длину самой длинной подстроки без повторяющихся символов".

        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);
}

Ответ 22

Вот два способа подхода к этой проблеме в JavaScript.

A Метод Brute Force состоит в том, чтобы дважды прокручивать строку, проверяя каждую подстроку на каждую другую подстроку и находим максимальную длину, где подстрока уникальна. Нам понадобятся две функции: одна, чтобы проверить, является ли подстрока уникальной, и вторая функция для выполнения нашего двойного цикла.

// 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;
  }
}

У этого есть временная сложность O(n^3), поскольку мы выполняем двойной цикл O(n^2), а затем еще один цикл поверх этого O(n) для нашей уникальной функции. Пространство - это размер нашего набора, который может быть обобщен на O(n) или более точно O(k), где k - размер набора.

A Жадный подход - это цикл только один раз и отслеживать максимальную уникальную длину подстроки по мере продвижения. Мы можем использовать либо массив, либо хэш-карту, но я думаю, что новый метод . Include() - это классно, поэтому позвольте использовать это.

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;
}

Это имеет временную сложность O(n) и пространственную сложность O(1).

Ответ 23

Вопрос: Найти самую длинную подстроку без повторяющихся символов. Пример 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;
        }

    }

если вам нужна самая длинная строка без повторяющихся символов в качестве выходных данных, сделайте это внутри цикла 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);

Ответ 24

Эта проблема может быть решена за O (n) временной сложности. Инициализируйте три переменные

  1. Начало (индекс указывает на начало неповторяющейся подстроки, Инициализируйте его как 0).
  2. Конец (индекс, указывающий на конец неповторяющейся подстроки, Инициализируйте его как 0)
  3. Hasmap (Объект, содержащий последние посещенные позиции индекса символов. Пример: {'a': 0, 'b': 1} для строки "ab")

Шаги: переберите строку и выполните следующие действия.

  1. Если текущий символ отсутствует в hashmap(), добавьте его как hashmap, символ в качестве ключа и его индекс в качестве значения.
  2. Если текущий символ присутствует в hashmap, то

    a) Проверьте, является ли начальный индекс меньше или равен значению, присутствующему в хэш-карте для символа (последний индекс того же символа, который был ранее посещен),

    б) меньше назначенного значения начальных переменных в качестве значения хеш-карт + 1 (последний посещенный ранее индекс того же символа + 1);

    c) Обновите хэш-карту, переопределив текущее значение символа хэш-карты в качестве текущего индекса символа.

    d) Рассчитать end-start как самое длинное значение подстроки и обновить, если оно больше, чем самая длинная неповторяющаяся подстрока.

Ниже приведено решение Javascript для этой проблемы.

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;
};

Ответ 25

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

Ответ 26

Можем ли мы использовать что-то вроде этого.

def longestpalindrome(str1):
    arr1=list(str1)
    s=set(arr1)
    arr2=list(s)
    return len(arr2)



str1='abadef'
a=longestpalindrome(str1)
print(a)

если только длина подстроки должна быть возвращена

Ответ 27

Алгоритм:
1) Инициализируйте пустой словарь dct, чтобы проверить, существует ли какой-либо символ в строке.
2) cnt - вести подсчет подстроки без повторяющихся символов.
3) l и r - два указателя, инициализированные первым индексом строки.
4) перебрать каждый символ строки.
5) Если символ отсутствует в dct, добавьте его и увеличьте cnt.
6) Если он уже присутствует, проверьте, больше ли cnt, чем resStrLen.
7) Уберите символ из dct и сдвиньте левый указатель на 1 и уменьшите счет.
8) Повторите 5,6,7 до l, r больше или равно длине входной строки.
9) В конце сделайте еще одну проверку, чтобы обрабатывать такие случаи, как входная строка с неповторяющимися символами.

Вот простая программа на Python для поиска самой длинной подстроки без повторяющихся символов


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]



Ответ 28

Решение в С.

#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;
}

Ответ 29

public int lengthOfLongestSubstring(String s) {
    int startIndex = 0;
    int maxLength = 0;
    //since we have 256 ascii chars
    int[] lst = new int[256];
    Arrays.fill(lst,-1);
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        //to get ascii value of c
        int ic = (int) c;
        int value = lst[ic];
        //this will say to move start index to next index of the repeating char
        //we only do this if the repeating char index is greater than start index
        if (value >= startIndex) {
            maxLength = Math.max(maxLength, i - startIndex);
            startIndex = value + 1;
        }
        lst[ic] = i;
    }
    //when we came to an end of string
    return Math.max(maxLength,s.length()-startIndex);
}

Это самый быстрый и линейный время и постоянное пространство

Ответ 30

Я реализовал подобное решение в Java. Я возвращаю длину строки вместо всей строки.

Найдите ниже решение для ссылки:

public int getLengthOfLongestSubstring(String input) {
        char[] chars = input.toCharArray();
        String longestString = "";
        String oldString="";
        for(int i= 0; i < chars.length;i++) {
            if (longestString.contains(String.valueOf(chars[i])))
            {
                if(longestString.length() > oldString.length()){
                    oldString = longestString;
                }
                if(longestString.split(String.valueOf(chars[i])).length>1)
                    longestString= longestString.split(String.valueOf(chars[i]))[1]+(chars[i]);
                else{
                    longestString =String.valueOf(chars[i]);
                }
            }
            else{
                longestString =longestString+chars[i];
            }
        }
        return  oldString.length()< longestString.length()? longestString.length(): oldString.length();
    }

Или можете использовать следующую ссылку в качестве ссылки.

Git URL