leetcode 3 Longest Substring Without Repeating Characters最长无重复子串

简介: Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating lett...

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.


这个应该是一个典型的动态规划问题:http://bbs.csdn.net/topics/310174805

直观地得到一个思路,表达起来真够难的,直接写代码要更容易

以abcbef这个串为例
用一个数据结构pos记录每个元素曾出现的下标,初始为-1
从s[0]开始,pos['a'] == -1,说明a还未出现过,令pos['a'] = 0,视为将a"加入当前串",同时长度++
同理令pos['b'] = 1,pos['c'] = 2
到s[3]时,pos['b'] != -1,说明'b'在前面已经出现过了,此时可得到一个不重复串"abc",刷新当前的最大长度,然后做如下处理:
pos[s[0~2]] = -1,亦即将"ab""移出当前串",同时当前长度减去3

重复以上过程

int lengthOfLongestSubstring(string s) {
        vector<int> dict(256, -1);
        int maxLen = 0, start = -1;
        for (int i = 0; i != s.length(); i++) {
            if (dict[s[i]] > start)
                start = dict[s[i]];
            dict[s[i]] = i;
            maxLen = max(maxLen, i - start);
        }
        return maxLen;
    }


/**
 * Solution (DP, O(n)):
 *
 * Assume L[i] = s[m...i], denotes the longest substring without repeating
 * characters that ends up at s[i], and we keep a hashmap for every
 * characters between m ... i, while storing <character, index> in the
 * hashmap.
 * We know that each character will appear only once.
 * Then to find s[i+1]:
 * 1) if s[i+1] does not appear in hashmap
 *    we can just add s[i+1] to hash map. and L[i+1] = s[m...i+1]
 * 2) if s[i+1] exists in hashmap, and the hashmap value (the index) is k
 *    let m = max(m, k), then L[i+1] = s[m...i+1], we also need to update
 *    entry in hashmap to mark the latest occurency of s[i+1].
 *
 * Since we scan the string for only once, and the 'm' will also move from
 * beginning to end for at most once. Overall complexity is O(n).
 *
 * If characters are all in ASCII, we could use array to mimic hashmap.
 */

int lengthOfLongestSubstring(string s) {
    // for ASCII char sequence, use this as a hashmap
    vector<int> charIndex(256, -1);
    int longest = 0, m = 0;

    for (int i = 0; i < s.length(); i++) {
        m = max(charIndex[s[i]] + 1, m);    // automatically takes care of -1 case
        charIndex[s[i]] = i;
        longest = max(longest, i - m + 1);
    }

    return longest;
}


下面给出python代码:

class Solution:
    # @return an integer
    def lengthOfLongestSubstring(self, s):
        start = maxLength = 0
        usedChar = {}

        for i in range(len(s)):
            if s[i] in usedChar and start <= usedChar[s[i]]:
                start = usedChar[s[i]] + 1
            else:
                maxLength = max(maxLength, i - start + 1)

            usedChar[s[i]] = i

        return maxLength
下面是c语言的版本:


// testlongsetString.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include<iostream>

using namespace std;

void GetMaxUnRepeatSubStr(char *str)
{
	//global var
	int hashTable[256] ={0};
	char* pMS = str;
	int mLen = 0;

	//temp var
	char* pStart = pMS;
	int len = mLen;
	char* p = pStart;
	while(*p != '\0')
	{
		if(hashTable[*p] == 1)
		{
			if(len > mLen)
			{
				pMS = pStart;
				mLen = len;
			}

			while(*pStart != *p)
			{
				hashTable[*pStart] = 0;
				pStart++;
				len--;
			}
			pStart++;
		}
		else
		{
			hashTable[*p] = 1;
			len++;
		}
		p++;
	}
	// check the last time
	if(len > mLen)
	{
		pMS = pStart;
		mLen = len;
	}
	//print the longest substring
	while(mLen>0)
	{
		cout<<*pMS<<" ";
		mLen--;
		pMS++;
	}
	cout<<endl;
}

int main()
{
	char* str1="bdabcdcf";
	GetMaxUnRepeatSubStr(str1);
	char* str2="abcdefb";
	GetMaxUnRepeatSubStr(str2);
	char* str3="abcbef";
	GetMaxUnRepeatSubStr(str3);

	return 0;
}


参考文献:







相关文章
|
5月前
Leetcode 516. Longest Palindromic Subsequence
找到一个字符串的最长回文子序列,这里注意回文子串和回文序列的区别。子序列不要求连续,子串(substring)是要求连续的。leetcode 5. Longest Palindromic Substring就是求连续子串的。
22 0
|
5月前
|
Java
Leetcode 3. Longest Substring Without Repeating Characters
此题题意是找出一个不包含相同字母的最长子串,题目给出了两个例子来说明题意,但这两个例子具有误导性,让你误以为字符串中只有小写字母。还好我是心机boy,我把大写字母的情况也给考虑进去了,不过。。。。字符串里竟然有特殊字符,于是贡献了一次wrong answer,这次我把ascii字符表都考虑进去,然后就没问题了。这个故事告诫我们在编程处理问题的时候一定要注意输入数据的范围,面试中可以和面试官去确认数据范围,也能显得你比较严谨。
27 3
LeetCode 424. Longest Repeating Character Replacem
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
75 0
LeetCode 424. Longest Repeating Character Replacem
LeetCode 409. Longest Palindrome
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。 在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。
54 0
LeetCode 409. Longest Palindrome
LeetCode 395. Longest Substring with At Least K
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
57 0
LeetCode 395. Longest Substring with At Least K
|
Windows
LeetCode 388. Longest Absolute File Path
我们致力于寻找我们文件系统中文件的最长 (按字符的数量统计) 绝对路径。例如,在上述的第二个例子中,最长路径为 "dir/subdir2/subsubdir2/file2.ext",其长度为 32 (不包含双引号)。
52 0
LeetCode 388. Longest Absolute File Path
|
存储
LeetCode 329. Longest Increasing Path in a Matrix
给定一个整数矩阵,找出最长递增路径的长度。 对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
45 0
LeetCode 329. Longest Increasing Path in a Matrix
|
29天前
|
机器学习/深度学习 算法
力扣刷题日常(一)
力扣刷题日常(一)
20 2
|
1月前
|
存储 索引
《LeetCode》—— LeetCode刷题日记
《LeetCode》—— LeetCode刷题日记
|
1月前
|
搜索推荐
《LeetCode》——LeetCode刷题日记3
《LeetCode》——LeetCode刷题日记3