zoukankan      html  css  js  c++  java
  • 剑指 Offer 48. 最长不含重复字符的子字符串

    思路

    方法一:暴力法

    对于字符串s,用f[i]表示以s[i]开头的无重复字符的字符串最大长度,

    逐一求出f[0], f[1], ... ,f[s.length()-1] ,最后返回这些值中的最大值即可。

     1 class Solution {
     2 public:
     3     int lengthOfLongestSubstring(string s) {
     4         if(s.empty())
     5             return 0;
     6         //f[i]表示以字符s[i]开头的最长无重复字符串
     7         vector<int> f(s.size(), 0);
     8         unordered_map<char, bool> vis; 
     9 
    10         for(int i = 0; i < s.length(); ++i) {
    11             vis[s[i]] = true;
    12             f[i] = 1;
    13             for(int j = i+1; j < s.length(); ++j) {
    14                 if(!vis[s[j]]) {
    15                     vis[s[j]] = true;
    16                     f[i]++;
    17                 } else {
    18                     for(int k = i; k <= j; ++k) {
    19                         if(vis[s[k]])
    20                             vis[s[k]] = false;
    21                     }
    22                     break;
    23                 }
    24             }
    25         }
    26 
    27         int maxlen = -1;
    28         for(int i = 0; i < f.size(); ++i) {
    29             if(f[i] > maxlen)  
    30                 maxlen = f[i];
    31         }
    32 
    33         return maxlen;
    34     }
    35 };

    复杂度分析

    时间复杂度:O(n2)

    空间复杂度:O(n)

    空间优化:由于最后只需要求f[]数组中的最大值,所以可以只用一个表示最大值的变量来代替f[]数组,这样可以减少n个大小的空间,但空间复杂度还是O(n),因为unordered_map仍然需要O(n)的空间。

    以下方法都参考题解:面试题48. 最长不含重复字符的子字符串(动态规划 / 双指针 + 哈希表,清晰图解)

    方法二:动态规划

    方法2.1 动态规划 + 哈希表

     1 class Solution {
     2 public:
     3     int lengthOfLongestSubstring(string s) {
     4         if(s.empty())
     5             return 0;
     6         unordered_map<char, int> dic;
     7         vector<int> dp(s.size());
     8         dp[0] = 1;
     9         dic[s[0]] = 0;
    10 
    11         int i = -1;
    12         for(int j = 1; j < s.size(); ++j) {
    13             //获取索引位置i
    14             if(dic.count(s[j]) == 1)
    15                 i = dic[s[j]];
    16             else
    17                 i = -1; 
    18             
    19             dic[s[j]] = j;  //更新哈希表
    20 
    21             if(dp[j-1] < j-i) {
    22                 dp[j] = dp[j-1] + 1;
    23             } else {
    24                 dp[j] = j-i;
    25             }
    26         }
    27 
    28         //返回dp数组中的最大值
    29         int res = dp[0];
    30         for(int j = 1; j < dp.size(); ++j) {
    31             if(dp[j] > res)
    32                 res = dp[j];
    33         }
    34 
    35         return res;
    36     }
    37 };

     

     空间优化后的代码如下:

     1 class Solution {
     2 public:
     3     int lengthOfLongestSubstring(string s) {
     4         unordered_map<char, int> dic;
     5         int res = 0;
     6 
     7         int i = -1;
     8         int tmp = 0;
     9         for(int j = 0; j < s.size(); ++j) {
    10             if(dic.count(s[j]) == 1)
    11                 i = dic[s[j]];
    12             else
    13                 i = -1; 
    14             
    15             dic[s[j]] = j;
    16             
    17             if(tmp < j-i) {
    18                 tmp = tmp + 1;
    19             } else {
    20                 tmp = j-i;
    21             }
    22 
    23             res = max(res, tmp);
    24         }
    25 
    26         return res;
    27     }
    28 };

     

    方法2.2 动态规划 + 线性遍历

     

     1 class Solution {
     2 public:
     3     int lengthOfLongestSubstring(string s) {
     4         int res = 0;
     5         int tmp = 0;
     6 
     7         for(int j = 0; j < s.size(); ++j) {
     8             int i = j-1;
     9             while(i >= 0 && s[i] != s[j]) {
    10                 --i;    //线性查找
    11             }
    12 
    13             if(tmp < j-i) {
    14                 tmp = tmp + 1;
    15             } else {
    16                 tmp = j-i;
    17             }
    18 
    19             res = max(res, tmp);
    20         }
    21 
    22         return res;
    23     }
    24 };

    方法三:双指针 + 哈希表 (滑动窗口)

     1 class Solution {
     2 public:
     3     int lengthOfLongestSubstring(string s) {
     4         unordered_map<char, int> dic;
     5         int i = -1, res = 0;
     6         for(int j = 0; j < s.length(); j++) {
     7             if(dic.count(s[j]) == 1)
     8                 i = max(i, dic[s[j]]);  // 更新左指针 i
     9             dic[s[j]] = j;    // 更新哈希表记录
    10             res = max(res, j - i); // 更新结果
    11         }
    12 
    13         return res;
    14     }
    15 };
  • 相关阅读:
    ptrace
    CentOS 5.4 final下Systemtap的安装
    SystemTap 静态探针安装包
    sysdig
    ORACLE 内部原理
    An introduction to KProbes
    CentOS6.5升级手动安装GCC4.8.2 与 CentOS 6.4 编译安装 gcc 4.8.1
    在Oracle Linux上安装dtrace
    dwarf调试信息格式入门
    MySQL 5.6.20-4 and Oracle Linux DTrace
  • 原文地址:https://www.cnblogs.com/FengZeng666/p/13945556.html
Copyright © 2011-2022 走看看