3、无重复字符的最长子串-cangjie

题目

3、无重复字符的最长子串

思路

哈希表记录是否有重复,驱动双指针滑动窗口

代码

class Solution {
    func lengthOfLongestSubstring(s: String): Int64 {
        let len = s.size. // 输入长度
        if(len < 2){ // 特殊情况
            return len
        }
        var r = 1 // 右指针的初始位置
        var res = 1 // 记录最长子串的长度
        var duplicate:Int8 = -1 // 记录重复字符
        var hash = HashSet<UInt8>() 
        for(left in 0..len){
            // println("left ${left} duplicate ${duplicate} s[left] ${s[left]}")
            if(duplicate >= 0){ // 存在重复字符
                hash.remove(s[left-1]) // 删除上个左字符
                // println("remove ${s[left-1]} because duplicate ${duplicate}")
                if(s[left-1] == UInt8(duplicate)){ // 如果去重成功,则初始化duplicate
                    duplicate = -1
                    r = max(r, left +1) // 更新右指针,防止相同字符连续出现导致连续消除
                }
                // println("duplicate ${duplicate}")
            }
            hash.put(s[left]) // 左字符入hash
            
            // print("myset ")
            // for (i in hash) {
            //     print("${i} ")
            // }
            // println("")
            
            for(right in r..len){
                r = right
                
                // println("s[right] ${s[right]}")
                // println("hash.contains(s[right] = ${hash.contains(s[right])}")
                
                if(hash.contains(s[right])){ // 发现重复字符,记录
                    duplicate = Int8(s[right])
                    break
                }
                hash.put(s[right]) // 右字符入hash
                res = max(res, hash.size) // 更新答案
                // println("res = ${res}")
                if(right == len - 1){ // 遍历到底,直接返回
                    return res
                }
            }
        }
        return res
    }
}

复杂度

平均情况

时间复杂度
  1. 遍历字符串:外层循环是通过左指针遍历整个字符串,时间复杂度为 O(n),其中 n 是字符串的长度。

  2. 内层循环:内层循环是通过右指针从当前右边界 r 向右遍历,每个位置最多只会被访问一次,因此在整个执行过程中,所有的字符总共也只会被访问一次,因此内层循环的总体时间复杂度也是 O(n)

  3. 哈希集合的操作:插入、删除和查找操作在哈希集合中平均时间复杂度为 (O(1))。

结合以上分析,外层和内层循环虽然各自是线性的,但在平均情况下没有重复的情况下,整体复杂度仍然保持在 O(n)

因此,时间复杂度是 O(n)

空间复杂度
  1. 哈希集合:根据输入字符串的不同字符,哈希集合会使用额外的空间来存储字符。在最坏情况下,当字符串包含 m 个不同字符时,空间复杂度为 O(m),其中 m 是字符集的大小。

因此,空间复杂度是 O(m),在 ASCII 字符集上通常为常数复杂度 O(1),但是如果考虑 Unicode 字符集可能会更大。

最坏情况

最坏情况的时间复杂度
  1. 字符串特征: 在最坏情况下,输入字符串可能全部由相同的字符组成,比如 "aaaaaa"。这意味着无论左指针或右指针如何移动,总会发现重复字符。

  2. 外层循环: 外层循环会遍历整个字符串,一共进行 n 次迭代,其中 n是字符串的长度。

  3. 内层循环: 在最坏情况下,右指针从当前位置 r 到字符串末尾的每次推进都会遭遇重复,导致内层循环结束后重新进入外层循环。因此,右指针可能需要在每次外层循环中几乎遍历整条链(即从当前左右指针的相对位置到末尾)。

因此,内层循环的复杂度在最坏情况下也可能接近 O(n)

在这个特殊情况下,即每个字符都是重复的,内外层循环可能会导致重复的遍历,因此最坏的时间复杂度可表示为 O(n^2)

最坏情况的空间复杂度

和平均一样

遇到的坑

1、家人们谁懂啊,仓颉的s[i]居然是UInt8,string的分量居然不是rune(char)

在这里插入图片描述

结果

pass

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值