LeetCode(题解)无重复字符的最长子串

题目

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

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串

先来看我自己的解法

package day01;

import java.util.Arrays;

public class 无重复字符的最长子串 {
    public static void main(String[] args) {
        int aa = lengthOfLongestSubstring("abcabcbb");
        System.out.println(aa);
    }

    /*
    * 思路如下:
    *   snum是存储了以每一个字符开头的不重复字符串的长度
    *    //如果字符串为空或者字符串的长度为1 就之间返回字符串的长度
    *    //先将字符串转换为字符数组 定义一个字符串curS,用来存放不重复的字符串,定义一个开关isStr,默认false,表示当前curS没有重复的字符串。
    *    //第一层循环 遍历字符数组 先将自身添加到curS里面,因为自身也算在长度里面
    *    //第二层循环 匹配不重复字符串.
        *    可以解决abca的重复字符串 只能找出下次以自身开头的字符串截止(比如 以a开头去匹配不重复,那么只能找到以a结尾的不重复字符串)
        *    如果是abcba 那么第二层循环只能找出abcb 中间的就不能匹配到
    *    //第三层循环 是为了解决中间的字符和后面字符的匹配问题
    *         每次去遍历curS字符串,如果curS中的字符串和char[j]匹配到,就将isStr为true(代表找到了重复字符串),退出循环
    *
    *    //回到第二层循环
        *    如果isStr为true  将curs的长度存储到snum里面去,并将curS置空,方便下次循环,isStr=false,并退出第二次循环
        *    如果isStr为false, 没有在curs找到重复的字符串
        *       需要判断第二层循环的索引j 是否到达了字符串的末尾
        *           如果没有到达末尾 就将char[j]添加到curS里面去
        *           如果到达了末尾,就相当于以当前字符开头到字符串末尾,都没有找到重复的字符串
        *               就需要将当前curS的长度+1 放入snum里面去,为什么要加一呢? 因为需要将最后一个字符也要算进去,并将curS置空
        *               比如pwwkew 以k字串开头到末尾都没有找到重复的字符串,就需要在第二层循环索引j指向w
        *               的时候将k开头的字符添加到snum里面去。
        *
    *
    *
    * */

    public static int lengthOfLongestSubstring(String s) {
        //如果字符串为空或者字符串的长度为1 就之间返回字符串的长度
        if(s.length() == 0 || s.length() ==1){
            return  s.length();
        }
        int[] snum = new int[s.length()]; //用来存储以每个字符开头的无重复字符的长度
        char[] chars = s.toCharArray();
        //用来表明是否找到了重复的字符串
        boolean isStr = false;
        //记录当前字符串里面的不重复字串
        String curS = "";
        for (int i = 0; i < chars.length; i++) {
            curS+=chars[i];
            for (int j = i+1; j < chars.length; j++) {
                    for (int k = 0; k < curS.length(); k++) {
                        if(curS.charAt(k)==chars[j]) {
                            isStr = true;
                            break;
                        }
                    }
                    if(isStr){
                        snum[i] = curS.length();
                        curS = "";
                        isStr = false;
                        break;
                    }else{
                        if(j!=chars.length-1){
                            curS+=chars[j];
                        }else{
                            snum[i]  = curS.length()+1;
                            curS = "";

                        }
                    }
                }
            }

        int num = 0;
        for (int i = 0; i < snum.length; i++) {
            if(snum[i]>num){
                num = snum[i];
            }
        }
        return  num;
    }
}

是否感觉写的有点复杂…哈哈哈 可能是我有点傻,竟然把时间复杂度写道了O(n3).
看我在力扣上的运行
在这里插入图片描述
结果只超过了 百分之五的用户,哈哈哈哈.

再来看别人的解法

//移动窗口解法 始终保持在[start,end]里面没有重复的子串,并求出最大的长度
    public  static  int lengthOfLongestSubstring1(String s){
        int n = s.length(),ans=0; //ans表示字符串不重复字符的最大长度
        Map<Character, Integer> map = new HashMap<>();
        for (int start = 0,end=0; end < n; end++) {
            char alpha = s.charAt(end);
            if(map.containsKey(alpha)){
                //如果发现了重复的字符串,就需要更新start位置,要保证[start,end]没有重复的字符串
                //+1是表示移动到不重复的下一个字符
                start = Math.max(map.get(alpha)+1,start);
            }

            ans = Math.max(ans,end-start+1);
            //用来存储字符所在的位置.,遇到重复的字符,会覆盖前面字符的位置.
            map.put(s.charAt(end),end);
        }
        return  ans;
    }

别人简简单单10多行代码就解决了问题,时间复杂度o(n)。
看来还是我太蠢了,继续加油,冲冲冲。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值