LeetCode 3. Longest Substring Without Repeating Characters

求一个字符串中无重复元素的最长子串。

解法很多。总的来说,因为 java 封装了很多类,类内的函数也多,所以比C++更好实现。

解法一:brute force O(n^3)

  枚举每一个子串O(n^2),判断其中有没有重复元素(使用java中的hashset判断某元素是否在集合中O(1),判断子串中有无重复元素O(n),C++标准模板库中的 unordered_map 可以代替),复杂度为 O(n^3)。

解法二:sliding windows O(2n)

  设置一个起始位置为 i j 的滑块,不断 extend the range [ i, j ]。同样使用 hashset/unordered_map 维护。若 s[j] 不存在于set,则加上 s[j],j++。否则判断并记录当前子串长度是否为最长,开始坐标移动到上一个 s[j] 的下一个位置,同时将这中间的元素移除set。(起始坐标的设置很关键,否则无法移除这些元素)。最终返回最长的范围。

解法三:

  对解法二的优化。只更新map(映射对不能用set存储) 中元素的位置,通过判断 s[j] 与 起始位置的关系来判断 s[j] 是否在 子串中出现过,而不移除元素,直接移动 i 的位置。省去了移除所产生的复杂度,所以O(2n)-O(n)=O(n).

解法四:

  对解法三的优化。不使用map存储映射对,因为输入的字符集范围有限(256 for extended ascll),所以使用长度为256的数组存储映射关系即可。

注:使用java的时候,解法三可以用queue实现,不标记起始位置,而直接压入元素或者弹出元素,但是判断某元素是否在队列出现过这个过程,由于c++标准模板库中的queue不支持迭代器,所以无法实现。java中queue.contains()可以实现。

解法三代码:

#include <unordered_map>
using namespace std;

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        
        unordered_map <int,int> a;
          int i=0,j=0,ans=0,n=s.length();
          for(;j<n;j++){
              if (a.count(s[j])){
                  auto iter=a.find(s[j]);
                int temp=iter->second;
                  i=temp>i?temp:i;
                  a.erase(s[j]);
              }//if    
              a.insert(pair<int,int>(s[j],j+1));
              ans=(j-i+1)>ans?j-i+1:ans;
          }//for
          return ans;
    }
};

注意 i=j 的时候,子串长度为1,所以注意始末坐标的位置含义。

猜你喜欢

转载自www.cnblogs.com/travelller/p/9124140.html
今日推荐