leetcode最长公共子串_(LeetCode刷题)Day03 无重复字符的最长子串

@TOC

鸣谢: LeetCode-In-Go

3. 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.

6552cbfb05b70926b138845df89d1733.png

在这里插入图片描述

970e20d849bef9985b1e00934d3d210b.png

解题思路

利用s[left:i+1]来表示s[:i+1]中的包含s[i]的最长子字符串。location[s[i]]是字符s[i]在s[:i+1]中倒数第二次出现的序列号。当left < location[s[i]]的时候,说明字符s[i]出现了两次。需要设置 left = location[s[i]] + 1,保证字符s[i]只出现一次。

提交代码

解法一、滑动窗口法

e5569c3aa0a3a6f8186f7db1ddff4082.png


时间复杂度:O(n^2)

空间复杂度:O(1)

C++代码

class Solution{public:    int lengthOfLongestSubstring(string s)    {        //s[start,end) 前面包含 后面不包含        int start(0), end(0), length(0), result(0);        int sSize = int(s.size());        while (end < sSize)        {            char tmpChar = s[end];            for (int index = start; index < end; index++)            {                if (tmpChar == s[index])                {                    start = index + 1;                    length = end - start;                    break;                }            }            end++;            length++;            result = max(result, length);        }        return result;    }};

Golang代码

// 解题思路/*利用s[left:i+1]来表示s[:i+1]中的包含s[i]的最长子字符串。location[s[i]]是字符s[i]在s[:i+1]中倒数第二次出现的序列号。当left < location[s[i]]的时候,说明字符s[i]出现了两次。需要设置 left = location[s[i]] + 1,保证字符s[i]只出现一次。*/func lengthOfLongestSubstring(s string) int {    if len(s) == 0 {        return 0    }    // location[s[i]] == j 表示:    // s中第i个字符串,上次出现在s的j位置,所以,在s[j + 1:i]中没有s[i]    // location[s[i]] == -1: s[i] 在s中第一次出现    location := [256]int{}  // 只有256长是因为,假定输入的字符串只有ASCII字符    for i := range location {        location[i] = -1    // 先设置所有字符都是没有碰到过的    }    maxLen, left := 0,0    for i := 0; i < len(s); i++ {        // 说明s[i]已经在s[left:i+1]中重复了        // 并且s[i]上次出现的位置在location[s[i]]        if location[s[i]] >= left {            left = location[s[i]] + 1   // 在在s[left:i+1]中去除s[i]字符及其之前的部分        } else if i + 1 - left > maxLen {            maxLen = i + 1 - left        }        location[s[i]] = i    }    return maxLen}

范例题解 - 4ms

3cf13e2ccafd3fdbbf754a14b8c479be.png
// 整体思想是一样的,存放数据的位置的结构换成了mapfunc lengthOfLongestSubstring(s string) int {    if len(s) == 0 {        return 0    }    maxLength := 0    start := 0    charMap := make(map[rune]int)    //go中的string底层是通过byte来实现的    for i, ch := range []rune(s){        if  lastPos, ok := charMap[ch];ok && lastPos >= start{            start = lastPos + 1        }        if i - start + 1 > maxLength {            maxLength = i - start + 1        }        charMap[ch] = i    }    return maxLength}

范例题解 - 0ms

这个方法去掉了存储位置的数据结构,直接在循环里面进行数据的比较和判断。

func lengthOfLongestSubstring(s string) int {    if len(s) == 0 {        return 0    }    var sln int    for t, e, c, d := 0, -1, 0, 0; c < len(s); c++ {        for d = t; d <= e; d++ {            if s[d] == s[c] {                break            }        }        if d > e { // new char            e = c            if e-t+1 > sln {                sln = e - t + 1            }        } else { // existed            t = d + 1            e = c        }    }    return sln}

小结

利用Location保存字符上次出现的序列号,避免了查询工作。location和Two Sum中的m是一样的作用。

    // m 负责保存map[整数]整数的序列号    m := make(map[int]int, len(nums))

编写本地测试

package problem0003import (    "testing"    "github.com/stretchr/testify/assert")type para struct {    one string}type ans struct {    one int}type question struct {    p para    a ans}func Test_OK(t *testing.T) {    ast := assert.New(t)    qs := []question{        question{            p: para{                one: "abcabcbb",            },            a: ans{                one: 3,            },        },        question{            p: para{                one: "bbbbbbbb",            },            a: ans{                one: 1,            },        },        question{            p: para{                one: "pwwkew",            },            a: ans{                one: 3,            },        },    }    for _, q := range qs {        a, p := q.a, q.p        ast.Equal(a.one, lengthOfLongestSubstring(p.one), "输入:%v", p)    }}

解法二、利用HashMap优化

70750e9fe175295818133eb6f01ada2b.png

时间复杂度:O(n)

空间复杂度:O(n)

C++代码

class Solution{public:    int lengthOfLongestSubstring(string s)    {        //s[start,end) 前面包含 后面不包含        int start(0), end(0), length(0), result(0);        int sSize = int(s.size());        unordered_map hash;        while (end < sSize)        {            char tmpChar = s[end];            //仅当s[start,end) 中存在s[end]时更新start            if (hash.find(tmpChar) != hash.end() && hash[tmpChar] >= start)            {                start = hash[tmpChar] + 1;                length = end - start;            }            hash[tmpChar] = end;            end++;            length++;            result = max(result, length);        }        return result;    }};

作者:pinku-2

链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-cshi-xian-/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Golang代码

func lengthOfLongestSubstring(s string ) int {    var i, j int    i = 0    max := 0    m := []byte(s)    n := make(map[byte]int)    for j = 0; j  max {                max = j-i+1            }        }    }    return max}func delMap(l int,i int,m []byte,n map[byte]int){    if l>i{        for{            delete(n,m[i])            i++            if i>l{                break            }        }    }else{        delete(n,m[l])    }}

解法三、利用数组代替hashmap

c0f76b72538db57fc3b9df95dd2b47ed.png

时间复杂度: O(n)

控件复杂度: O(n)

C++代码

class Solution{public:    int lengthOfLongestSubstring(string s)    {        //s[start,end) 前面包含 后面不包含        int start(0), end(0), length(0), result(0);        int sSize = int(s.size());        vector vec(128, -1);        while (end < sSize)        {            char tmpChar = s[end];            //仅当s[start,end) 中存在s[end]时更新start            if (vec[int(tmpChar)] >= start)            {                start = vec[int(tmpChar)] + 1;                length = end - start;            }            vec[int(tmpChar)] = end;            end++;            length++;            result = max(result, length);        }        return result;    }};

作者:pinku-2

链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-cshi-xian-/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Golang代码

func lengthOfLongestSubstring(s string) int {    slen := len(s)    if slen == 0 {        return 0    }    dp := make([]int, 256)    str := []byte(s)    maxNum := 1    l := 0    h := 0    var flag bool    var sameChar byte    for l <= h && h < slen {        if flag {            dp[str[l]]--            if str[l] ==  sameChar && dp[str[l]] == 1 {                flag = false                sameChar = 0            }            l++            continue        }        if dp[str[h]] == 0 {            dp[str[h]] = 1            if h-l+1 > maxNum {                maxNum = h-l+1            }        }else {            dp[str[h]]++            flag = true            sameChar = str[h]        }        h++    }    return maxNum}
f1371baef92fc4065980559430ebc67a.png

成长,就是一个不动声色的过程,一个人熬过一些苦,才能无所不能。 ​​​​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值