Leetcode#3. Longest Substring Without Repeating Characters(最长不重复子串-哈希))

本文介绍了一种寻找字符串中最长不重复子串的算法,提供了两种C++实现方案及一种Python实现方案,并分析了各自的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given “abcabcbb”, the answer is “abc”, which the length is 3.

Given “bbbbb”, the answer is “b”, with the length of 1.

Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

题意

给你一个字符串,找出最长不重复子串的长度输出。
例如abcabcbb,答案是abc,长度为3。
思路:要找子串,肯定需要遍历每一个字符,求对应的子串。遍历的过程为:

a
ab
abc
abca
abcab
abcabc
abcabcb
abcabcbb
b
bc
bca
bcab
.......

但是里面有重复的像“abca”后面的以第一个a开头的都是不符合要求的,由此得出第一个a组成的最长子串为3,接下来考虑怎么去重,这时候我们可以用哈希,我们知道哈希就是要解决冲突问题呢,那个我们的解题思路就是从每一个字符为初始遍历其构成的子串,一旦出现哈希冲突就停止,同时保存此时的长度。

解法一:C++版 哈希

这里需要注意两点:

  • 字符串为1时单独输出。
  • 每次出现哈希冲突要重新初始化哈希数组。

时间复杂度:O(n*n)
运行时间:
这里写图片描述

class Solution {
public:
    int lengthOfLongestSubstring(string s) {

        int longest = 0;
        //以字符的ascii码作为下标a 97+26
        int hash[200];
        //初始化为0,出现过标记为1
        memset(hash,0,sizeof(hash));
        if(s.size()==1)
            return 1;

        for(int i=0; i<s.size(); i++)
        {
            hash[int(s[i])]=1;
            for(int j=i+1; j<=s.size(); j++)
            {
                if(hash[int(s[j])]==0&&j!=s.size())
                {
                    hash[int(s[j])]=1;
                }
                else
                {
                    if(longest<j-i)
                        longest = j-i;
                    memset(hash,0,sizeof(hash)); //注意每次都要初始化
                    break;
                }
            }
        }
        return longest;
    }
};

同样的解法,参考网上的解法发现我的代码在细节处理方面还不够好,下面是修改后的代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {

        int longest = 0, i ,j;
        //以字符的ascii码作为下标a 97+26
        int hash[200];
        for(i=0; i<s.size(); i++)
        {
            memset(hash,0,sizeof(hash)); //注意每次都要初始化
            hash[int(s[i])]=1;
            for(j=i+1; j<s.size(); j++)
            {
                if(hash[int(s[j])]==0)
                {
                    hash[int(s[j])]=1;
                }
                else
                {
                    if(longest<j-i)
                        longest = j-i; 
                    break;
                }
            }
            if(j==s.size() && longest<j-i)
            {
                longest = j-i;
            }
        }
        return longest;
    }
};

解法二:C++优化版

设置一个边界left,初始化为0,下面以第一个为例子:
a b c a b c b b
初始化left为0,代表比较的边界为0

  • 第一步: a hash[a]=-1 没有重复,更新hash[a] =0 ,ans = i-left+1=1(代表此时最大的不重复子串)
  • 第二步: b hash[b]=-1 没有重复 ,更新hash[b] =1 ,ans =2
  • 第三步: c hash[c]=-1 没有重复 , 更新hash[c]=2, ans =3
  • 第四步: a hash[a]=0 有重复 left前移动一位=1 hash[a]=4 ans =3
  • …….

    时间复杂度:O(n)
    运行时间:
    这里写图片描述

class Solution {
public:
    int lengthOfLongestSubstring(string s) {


        //left记录边界 即上次字符出现的位置
        int hash[200], ans = 0, left = 0, i, j;
        memset(hash, -1, sizeof(hash));
        for(i=0; i<s.size(); i++)
        {
             //出现重复字符,需要调整left的位置
             if(hash[int(s[i])]>=left)
                left = hash[int(s[i])] + 1;
             hash[int(s[i])]=i;
             ans = max(ans, i-left+1);
        }
        return ans;
    }
};

解法二:Python

第一种解法是python写果断超时,尝试第二种成功。Python的底层是c语言写的,导致运行时间长。
运行时间:
这里写图片描述
时间复杂度:O(n)

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        python中字符和ascii码的转换函数:
        ord('a')
        97
        chr(97)
        a
        字符串长度:len()
        """
        hash=[-1]*200
        ans = 0
        left = 0
        for i in range(0, len(s)):
            if hash[ord(s[i])]>=left:
                left = hash[ord(s[i])] + 1
            hash[ord(s[i])] = i
            ans = max(ans, i-left+1)
        return ans

本题github链接:https://github.com/xuna123/LeetCode/blob/master/Leetcode#3. Longest Substring Without Repeating Characters(最长不重复子串-哈希)) .md

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值