Leetcode——最長不重複子串

題:從一個字符串中找到一個連續子串,該子串中任何兩個字符不能相同,求子串的最大長度並輸出一條最長不重複子串。算法

本身的第一反應是使用動態規劃來解決這個問題。在蒐集資料以後,發現共有三種解決方案:
spa

  1. 使用hashcode

  2. 使用DP + Hash索引

==================================================================
字符串

基本方法,使用簡單Hashstring

其實判斷重複問題最應該想到的是Hash,創建一個簡單的hash table,key爲字符的ASCII碼值,value爲該字符是否已經在當前子串中出現過(出現過爲1,未出現爲0)。最簡單的方法就是對全部的子串進行查重,複雜度爲θ(n^2)。hash

在掃描過程當中,咱們須要找到儘量長的不重複子串,我稱之爲「極長不重複子串」。假設s[i...j]的當前的極長不重複子串爲L(i,j),那麼L(i, j+1)的長度分爲兩種狀況:it

    1. 上一個s[j+1]表明的字符出如今L(i.j)的起始位置以前,那麼s[j+1]應該被添加到當前極長不重複子串中;io

    2. 上一個s[j+1]表明的字符出如今L(i,j)的起始位置以後,那麼記錄下L(i,j),開始跟蹤新的極長不重複子串。
table

在掃描完全部的str[0...n],str[1...n],str[2...n]....後,最長的極長字符串就是字長不重複子串

源代碼爲:

/* 最長不重複子串 設串不超過30
 * 咱們記爲 LNRS
 */
int maxlen;
int maxindex;
void output(char * arr);
 
/* LNRS 基本算法 hash */
char visit[256];
 
void LNRS_hash(char * arr, int size)
{
    int i, j;
    for(i = 0; i < size; ++i)
    {
        memset(visit,0,sizeof visit);
        visit[arr[i]] = 1;
        for(j = i+1; j < size; ++j)
        {
            if(visit[arr[j]] == 0)
            {
                visit[arr[j]] = 1;
            }else
            {
                if(j-i > maxlen)
                {
                    maxlen = j - i;
                    maxindex = i;
                }
                break;
            }
        }
        if((j == size) && (j-i > maxlen))
        {
            maxlen = j - i;
            maxindex = i;
        }
    }
    output(arr);
}

=========================================================================

使用DP+hash。使用DP以空間換時間的方法來解決此問題,DP最重要的思想就是要記錄。

在第一種方法當中,咱們掃面了全部的子串。可是若是str1是str2的子串,那麼str1的最長不重複子串確定小於或者等於str2。咱們能夠直接掃描整個給定的字符串,並在掃描過程當中記錄下全部掃描到極大字符串,找到最長的便可(仿照人工的思路)。

使用hash表來保存一個字符最近被掃描的時候所處的位置

代碼以下:

class Solution 
{
public:
	int lengthOfLongestSubstring(string s) 
	{
		if (s.empty()) return 0;

		int visit[256];		//用來保存最近掃描到一個字符的位置
		int max_length;		//目前最大不重複子串的長度
		int start_index;	//目前最大不重複子串的起始索引
		int last_start;		//目前掃描的極大不重複子串的起始索引
		int last_length;	//目前掃描的極大不重複子串的長度

		start_index = 0;
		max_length = 0;
		last_start = 0;
		memset(visit, -1, sizeof(int) * 256);

		//第一個字符
		visit[s[0]] = 0;
		last_length = 1;

		for (int i = 1; i < s.size(); i++)
		{
			if (visit[s[i]] == -1)
			{
				last_length++;
				visit[s[i]] = i;
			}
			else if (visit[s[i]] < last_start)
			{
				last_length++;
				visit[s[i]] = i;
			}
			else
			{
				if (last_length > max_length)
				{
					max_length = last_length;
					start_index = last_start;
					last_start = visit[s[i]] + 1;		//更新當前極長子串的起點,是重複字符的後一位
					last_length = i - last_start + 1;
					visit[s[i]] = i;
				}
				else
				{
					last_start = visit[s[i]] + 1;
					last_length = i - last_start + 1;
					visit[s[i]] = i;
				}
			}
		}

		if (last_length > max_length)
		{
			max_length = last_length;
		}
		return max_length;
	}
};
相關文章
相關標籤/搜索