zoukankan      html  css  js  c++  java
  • [LeetCode] Longest Substring Without Repeating Characters | Two Pointers + Hash Map

    https://leetcode.com/problems/longest-substring-without-repeating-characters/?tab=Description

    要求在一个字符串中寻找最长的没有重复字符的子串。注意,是子串(substring),不是子序列(subsequence)。

    思路1:Brute Force

    暴力的做法简而言之就是:遍历字符串所有的位置,以这个位置为起点往前走,找出满足要求的子串。

    具体地,可以用两个指针维护子串的区间,每往前走一格,须要判断当前位置的字符在区间内是否重复出现(暴力的做法是扫描这个区间,较好的做法是用一个Hash Set存储区间内的元素,从而可以O(1)查找)。

    Time complexity: 最最暴力的算法是O(n^3),用Hash Set的话就是O(n^2)
    Space complexity: 用Hash Set的话就是O(字符种类数),否则O(1)

    ps. O(n^2)的算法可以AC

    参考代码(C++)

    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            int n = s.size();
            if (n == 0) return 0;
            if (n == 1) return 1;
            
            int ret = 1;
            int start = 0, end = 1;
            while (end < n) {
                int tmp_ret = 1;
                unordered_set<int> myset({s[start]});
                
                while (end < n && myset.find(s[end]) == myset.end()) {
                    myset.insert(s[end]);
                    tmp_ret++;
                    end++;
                }
                ret = max(ret, tmp_ret);
                start++; end = start + 1;
            }
            
            return ret;
        }
    };
    

    思路2:Sliding Window / Two Pointers

    将longest substring without repeating characters简称为"LSWRC"。

    扫描一遍字符串,对每个位置,计算以该位置的字符为终点的LSWRC的长度,取最大的。

    具体地,设字符串为s,用s[i]表示位置i的字符,设以s[i]为终点的LSWRC的长度对应的区间是[start, i]。然后据此计算位置i+1的LSWRC,分两种情况:

    1. 如果s[i+1]s[start...i]未出现,则新的区间为[start, i+1]
    2. 如果s[i+1]s[start...i]出现了,设出现的位置是p (start <= p <= i),则须要更新区间为[p+1, i+1]

    实现上,可以用两个变量维护区间的边界信息,用一个哈希表存储区间的元素以快速查找。这里有一个小技巧,不需要真的去存区间的元素,否则还要删除(虽然删除的开销并不大),直接存目前为止的所有元素,查找的时候如果找到了重复元素,再判断找到的元素是否在[start, i]区间内即可,不在的话就按情况1更新区间。

    Time complexity: O(n)
    Space complexity: O(字符种类数)

    参考代码(C++)

    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            int n = s.size();
            if (n == 0) return 0;
            if (n == 1) return 1;
            
            int ret = 1, cur_ret = 1;
            unordered_map<char, int> hash_map;  // key: element of s, value: index of the element
            hash_map[s[0]] = 0;
            
            int start = 0;
            for (int i = 1; i < n; ++i) {
                unordered_map<char, int>::iterator it = hash_map.find(s[i]);
                if (it == hash_map.end()) {
                    hash_map[s[i]] = i;
                } else {
                    if (it->second >= start) {
                        start = it->second + 1;
                    }
                    it->second = i;  // update the pos of repeated char
                }
                ret = max(ret, i-start+1);
            }
            
            return ret;
        }
    };
    
  • 相关阅读:
    MySql 用户 及权限操作
    MAC 重置MySQL root 密码
    在mac系统安装Apache Tomcat的详细步骤[转]
    Maven:mirror和repository 区别
    ES6 入门系列
    转场动画CALayer (Transition)
    OC 异常处理
    Foundation 框架
    Enum枚举
    Invalid App Store Icon. The App Store Icon in the asset catalog in 'xxx.app' can’t be transparent nor contain an alpha channel.
  • 原文地址:https://www.cnblogs.com/ilovezyg/p/6413081.html
Copyright © 2011-2022 走看看