Swift && LeetCode 第三题:无重复字符的最长子串

562 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

今天我们来看看第三题:无重复字符的最长子串

无重复字符的最长子串

题目描述:

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

解题思路

对于此类字符串操作,通常使用滑动窗口来解题。
滑动窗口的思想其实就是动态的移动窗口,而控制这个窗口的关键所在是left、right两个位置,满足条件更新right,不满足条件更新left

这题中的思路其实就是对字符串进行遍历,通过键值对keyValue来记录字符和字符数量。如果字符数量大于一说明有重复,则操作left,没有则继续操作right。

滑动窗口解法

解法一

class Solution { 
    func lengthOfLongestSubstring(_ s: String) -> Int { 
        var res = 0 
        var window = [Character: Int]() 
        var left = 0 
        var right = 0 
        while right < s.count { 
            let c = s[s.index(s.startIndex, offsetBy: right)] 
            right += 1 
            if window[c] != nil { 
                window[c]! += 1 
            } else { 
                window[c] = 1 
            } 
            while let value = window[c], value > 1 { 
                let d = s[s.index(s.startIndex, offsetBy: left)] 
                left += 1 
                if window[d] != nil { 
                    window[d]! -= 1 
                } else {
                    window[c] = 1 
                } 
            } 
            res = max(res, right - left)
       } 
       return res 
    } 
}

在以上这个解法中使用的键值对{key: value}key是字符,value是字符出现的数量,所以value没有的到很好的利用,每次左指针右移一位,移除字典中的一个字符,这一步会导致很多无用的循环。while循环发现的重复字符不一定就是字典中最早添加那个,还要好多次循环才能到达,这些都是无效循环,不如直接用map记下每个字符的索引。

在下面的解法中使用keyValue来记录字符和字符的索引index

解法二

class Solution { 
    func lengthOfLongestSubstring2(_ s: String) -> Int {
        var res = 0
        var window = [Character: Int]()
        var left = 0
        var right = 0
        for char in s {
            if let value = window[char] {
                left = max(value, left)
            }
            res = max(res, right-left+1)
            right += 1
            window[char] = right
        }
        return res
    }
}

总结

在解题时,最开始的方法可能不是最优解,但是只要我们的思路是对的就没问题,因为过程中会我们会发现前面的解法存在哪些问题,然后在去优化这些问题,在我看来,只要一直思考就是在进步。