LeetCode 003. Longest Substring Without Repeating Characters

3. Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring"pwke" is a subsequence and not a substring.

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    }
};
解题思路:
  • 自己的解题思路
运用动态规划进行求解。
dp[i] 是指字符串从头到 s[i] 所找到的最长无重复子字符串长度。因此,答案 dp[s.size()-1] 就是所要的结果。期间用到了辅助数组标记访问位。
时间复杂度为 O(n*n)
  • 别人的解题思路
通过增加一个 start 来记录当前子字符串的起始位置,利用辅助数组来记录字符上次出现的位置(这里有两种方法:方法 1 ,考虑所有 128 个字符;方法 2 ,利用 map, 可以只记录出现的字符)。
时间复杂度为 O(n*n)
学习收获:
  • 最近练的题目难度开始上升。有种无法总结的感觉,可能相关题目练的比较少。
  • fill ( last , last + ASCII_MAX , - 1 ); 新语法 fill()
  • map<char,int> charMap;
charMap.count(s[i])==0;
熟悉了 map 里面的 count()
附件:程序
1 、自己的程序:
int flag [ 128 ] = { 0 };
int getMax ( int x , int y )
{
     return x > y ? x : y ;
}
void init ( int * flag , int num )
{
     for ( int i = 0 ; i != num ; ++ i )
     {
         flag [ i ] = 0 ;
     }
}
class Solution
{
     public :
     int lengthOfLongestSubstring ( string s )
     {
         if ( s . size () == 0 ) { return 0 ; }
         vector < int > dp ( s . size (), 1 );
         for ( int i = 1 ; i != s . size (); ++ i )
         {
             int j = i ;
             int len = 0 ;
            //向前开始查找,找到以s[i]结尾的最长无重复子序列
             for (; ( j >= 0 ) && ( flag [ s [ j ]] == 0 ); -- j )
             {
                 flag [ s [ j ]] = 1 ;
                 ++ len ;
             }
             dp [ i ] = getMax ( dp [ i - 1 ], len );
             init ( flag , 128 );
         }
         return dp [ s . size () - 1 ];
     }
};
2 、别人的程序
版本 1 :使用了 map
class Solution
{
     public :
     int lengthOfLongestSubstring ( string s )
     {
         map < char , int > charMap ;
         int start = - 1 ;
         int maxLen = 0 ;
         for ( int i = 0 ; i < s . size (); i ++)
         {
             if ( charMap . count ( s [ i ]) != 0 )
             {   //更新开始位置,max()不能少
                 start = max ( charMap [ s [ i ]], start );
             }
             charMap [ s [ i ]] = i ;
             maxLen = max ( maxLen , i - start );
         }
         return maxLen ;
     }
};
版本 2 ,直接有点类似暴力,枚举出所有 char 取值
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 ;
}
版本 2 变形,比较两个版本,注意细节差异。
class Solution
{
     public :
     int lengthOfLongestSubstring ( string s )
     {
         const int ASCII_MAX = 255 ;
         int last [ ASCII_MAX ];
         int start = 0 ;
         fill ( last , last + ASCII_MAX , - 1 );
         int max_len = 0 ;
         for ( int i = 0 ; i < s . size (); i ++)
         {
             if ( last [ s [ i ]] >= start )
             {
                 max_len = max ( i - start , max_len );
                 start = last [ s [ i ]] + 1 ;
             }
             last [ s [ i ]] = i ;
         }
         return max (( int ) s . size () - start , max_len );
};
这个思路很简单,就是建个临时 str ,来存储当前遍历到的无重复子序列;再利用 string find() 进行查找。
但是,不知道为什么这个程序效率比上面的程序高。感觉效率不是很高。因为有 find(),erase() 这样可能 O(n) 的操作。
class Solution
{
     public :
     int lengthOfLongestSubstring ( string s )
     {
         int length = 0 , cur = 0 ;
         string str ;
         for ( int i = 0 ; i < s . size (); ++ i )
         {
             int pos = str . find ( s [ i ]);
             if ( pos != string :: npos )
             {
                 length = max ( length , ( int ) str . size ());
                 str . erase ( str . begin (), str . begin () + pos + 1 );
             }
             str . push_back ( s [ i ]);
         }
         return max ( length , ( int ) str . size ());
     }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值