1. 程式人生 > >LeetCode題解 || Longest Substring Without Repeating Characters (O(n)算法)問題

LeetCode題解 || Longest Substring Without Repeating Characters (O(n)算法)問題

data fun char with data- sts color leet not

problem:

Given a string, find the length of the longest substring without repeating characters. 
For example, the longest substring without repeating letters for "abcabcbb" is "abc", 
which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

thinking:

技術分享

(1)尋找子串,要做一次遍歷。

(2)暴力破解法,檢查每個子串,利用hash table的映射思想。開一個數組,下標為字符的ASCII碼,因為沒有說明字符串的類型,能夠採取一些措施壓縮hash table的大小。暴力破解法的最壞時間復雜度為O(n*n)

(3)發現一個O(n)的算法。非常贊

事實上,這裏非常多工作都是反復的、沒用的。
看一個樣例:
S="abbdeca"。
t1="abbdeca",t1[1]==t1[2]。
t2="bbdeca"。t2[0]==t2[1]。


t3="bdeca",一直掃描到最後。
t4="deca"、t5、t6、t7都同上。
我們在處理t1的時候已經掃描到了s[2],然後處理t3的時候掃描了s[2]到s[6],這兩個子串已經掃描完了整個母串。
換言之,能使得子串停止掃描的位置僅僅有兩處:1.s[2]。2.s[6](結尾)。


對於還有一個樣例S="aaab",能使子串停止掃描的位置各自是:s[1],s[2],s[3](結尾)。


所以我們能夠考慮僅僅掃描母串,直接從母串中取出最長的無反復子串。
對於s[i]:
1.s[i]沒有在當前子串中出現過。那麽子串的長度加1;
2.s[i]在當前子串中出現過,出現位置的下標為j。那麽新子串的起始位置必須大於j,為了使新子串盡可能的長,所以起始位置選為j+1。

code:

說明:凝視的解法復雜度為O(n*n),沒凝視的位O(n)

#include <iostream>
#include <string>
#include <memory.h>

using namespace std;
/*
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int a[100]; //壓縮hash table
        memset(a,0,sizeof(int)*100);
        int length = s.size();
        int index=0;
        int max=0;
        for(int i=0;i<length;i++)
        {
            int j=i;
            while((j<length)&&(a[s.at(j)-32]==0))//壓縮hash table
            {
                a[s.at(j)-32]=1;
                index++;
                j++;
            }
            memset(a,0,sizeof(int)*100);
            max=(max>index)?max:index;
            index=0;
            if(j==length-1) //這裏也有一個小技巧。能夠有效減少時間復雜度
                break;
        }
        return max;
    }
};
*/
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int locs[256];//保存字符上一次出現的位置
        memset(locs, -1, sizeof(locs));

        int idx = -1, max = 0;//idx為當前子串的開始位置-1
        for (int i = 0; i < s.size(); i++)
        {
            if (locs[s[i]] > idx)//假設當前字符出現過,那麽當前子串的起始位置為這個字符上一次出現的位置+1
            {
                idx = locs[s[i]];
            }

            if (i - idx > max)//這裏是關鍵!

!!!!!

!! { max = i - idx; } locs[s[i]] = i; } return max; } }; int main() { string str = "abcdab"; Solution mysolution; cout<<mysolution.lengthOfLongestSubstring(str)<<endl; }



LeetCode題解 || Longest Substring Without Repeating Characters (O(n)算法)問題