(Leetcode) [String] Longest substring without repeating characters

Topic: String
Difficulty: Medium


Question

Given a string s, find the length of the longest substring without repeating characters.
์ œ๋ชฉ ๊ทธ๋Œ€๋กœ ๋ฌธ์ž์—ด ๋‚ด์—์„œ ๋ฐ˜๋ณต๋˜๋Š” ์•ŒํŒŒ๋ฒณ์ด ์—†๋Š” ๊ฐ€์žฅ ๊ธด ๋ถ€๋ถ„ ๋ฌธ์ž์—ด์„ ์ฐพ๋Š” ๋ฌธ์ œ์ด๋‹ค.


My first solution: time complexity O(n^2)

๋ฌธ์ž์—ด์— ์ฒซ ์•ŒํŒŒ๋ฒณ์„ ๊ธฐ์ค€์ ์œผ๋กœ ์žก๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‘๋ฒˆ์งธ ์•ŒํŒŒ๋ฒณ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์ฐจ๋ก€๋Œ€๋กœ unordered_set์— ์ €์žฅ์„ ํ•œ๋‹ค. ํ•˜๋‚˜์˜ ์ •์ˆ˜ variable (int max)์„ ์„ธ์›Œ์„œ for loop์ด ํ•˜๋‚˜ ๋Œ ๋•Œ๋งˆ๋‹ค ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
์ด๋•Œ, ๋ฐ˜๋ณต๋˜๋Š” ์•ŒํŒŒ๋ฒณ์ด ๋‚˜์˜ค๋ฉด ๋‹ค์Œ ๊ธฐ์ค€ ์•ŒํŒŒ๋ฒณ์œผ๋กœ ๋„˜์–ด๊ฐ„๋‹ค. ์ด๋Ÿฐ์‹์œผ๋กœ ๊ฐ€์žฅ ํฐ max๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.
๋‘ ๊ฐœ์˜ for loop์ด ์‚ฌ์šฉ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— time complexity๋Š” O(n^2)์ด๋‹ค.
์„ธํŠธ์™€ ๋งต์ด๋ผ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋ฐฐ์›€์œผ๋กœ์จ ์กฐ๊ธˆ ๋” ์‰ฝ๊ฒŒ implement ํ•  ์ˆ˜ ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•๋“ค์ด ์ƒ๊ธด๋‹ค.

int lengthOfLongestSubstring(string s) {
    if (s.length()==0)
        return 0;

    int max = -1;
    int num = 0;
    for (int i=0; i<s.length(); i++) {
        unordered_set<char> set;
        num = 0;
        // vector<bool> set(26);   // default values in set are false
        for (int j=i; j<s.length(); j++) {
            // if (set[s[j]-'a'])
            //     break;
            // set[s[j]-'a']=true;
            if (set.find(s[j]) != set.end())
                break;
            set.insert(s[j]);
            num++;
        }
        cout << num << endl;
        if (max<num)
            max = num;
    }
    return max;
}

runtime์ด ์–ด๋งˆ๋ฌด์‹œํ•˜๋‹ค.
runtime-longest-substring-without-repeating-characters.png


Second solution: time complexity O(n)

๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ์ด๋ฏธ ๊ฑฐ์ณ๊ฐ„ ์•ŒํŒŒ๋ฒณ์˜ index๋ฅผ lastIndex๋ผ๋Š” ๋ฐฐ์—ด์— ์ €์žฅํ•จ์œผ๋กœ์จ linear time complexity๋ฅผ ๊ฐ€๋Šฅ์ผ€ ํ–ˆ๋‹ค.
int i๋ฅผ starting index๋กœ ๋‘๊ณ , int result๋ผ๋Š” ๋ณ€์ˆ˜์— ์ตœ๋Œ€ ๊ธธ์ด๋ฅผ ์ €์žฅํ•œ๋‹ค.
for loop ์•ˆ์—์„œ,

  1. first line: ๋งŒ์•ฝ ๋ฐ˜๋ณต๋˜๋Š” ์•ŒํŒŒ๋ฒณ์ด ๋‚˜์˜ค๋ฉด, i์— 1์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
  2. second line: ๋งŒ์•ฝ ํ˜„์žฌ i์—์„œ j๊นŒ์ง€์˜ ๊ธธ์ด๊ฐ€ ์ œ์ผ ๊ธธ๋ฉด, result์— ์—…๋ฐ์ดํŠธ ์‹œํ‚จ๋‹ค.
  3. third line: ๋งค๋ฒˆ ํŠน์ • ์•ŒํŒŒ๋ฒณ์ด ๋งˆ์ง€๋ง‰์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” index๋ฅผ ์—…๋ฐ์ดํŠธ ์‹œํ‚จ๋‹ค.

์ด๋Ÿฐ ๋ฐœ์ƒ์€ ๋Œ€์ฒด ์–ด๋–ป๊ฒŒ ํ•˜๋Š” ๊ฑธ๊นŒ. ๋Œ€๋‹จํ•˜๋‹ค.

int lengthOfLongestSubstring(string s) {
    int result = 0;

    // last index of all characters is initialized as -1
    vector<int> lastIndex(256, -1); // number of chars = 256

    int i = 0;  // start of window
    for (int j=0; j<s.length(); j++) {
        i = max(i, lastIndex[s[j]+1]);

        // update result if we get a larger window
        result = max(result, j-i+1);

        // update last index of j
        lastIndex[s[j]] = j;
    }
    return result;
}


Summary

์ด ๋ฌธ์ œ์—์„œ์˜ ๊ด€๊ฑด์€ ๋ชจ๋“  ์•ŒํŒŒ๋ฒณ์„ ๊ธฐ์ค€์ ์œผ๋กœ ๋‘์–ด์„œ ๊ฐ€์žฅ ๊ธธ๊ฒŒ ๋‚˜์˜ค๋Š” ๋ถ€๋ถ„ ๋ฌธ์ž์—ด์„ ์ฐพ์„๋•Œ ์–ผ๋งˆ๋‚˜ ํšจ์œจ์ ์œผ๋กœ ์ฐพ์„์ˆ˜ ์žˆ๋Š”์ง€ ์ด๋‹ค.
์ฒซ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ์ง๊ด€์ ์ด์ง€๋งŒ ๋‘ ๊ฐœ์˜ for loop์ด ์‚ฌ์šฉ๋˜์–ด์„œ time complexity๊ฐ€ O(n^2)์ด๋‹ค. ๋น„ํšจ์œจ์ ์ธ ํŽธ์ด๋‹ค.
๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ array๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ˜๋ณต๋˜๋Š” ์•ŒํŒŒ๋ฒณ์˜ index๋ฅผ ์ €์žฅํ•ด์„œ ๊ธฐ์ค€์ ์„ ๊ณ„์† ์ด๋™์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ํ•˜๋‚˜์˜ ๋ฃจํ”„๋งŒ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ธฐ์–ตํ•˜์ž. ๋ฐ˜๋ณต๋˜๋Š” ์•ŒํŒŒ๋ฒณ์˜ index๋ฅผ ์ €์žฅํ•ด์„œ ํ•˜๋‚˜์˜ ๋ฃจํ”„๋กœ ํšจ์œจ์„ฑ์„ ์ฆ๊ฐ€.


References

https://www.geeksforgeeks.org/length-of-the-longest-substring-without-repeating-characters/

Categories:

Updated:

Leave a comment