Longest Substring Without Repeating Characters (最长不重复字符的子序列) Java-O(n)解法

先把原题目po出来以示敬意

https://leetcode.com/problems/longest-substring-without-repeating-characters/

题目:给一个字符串,找出其中最长的子串,并且该自串没有重复字符

由于我是算法的新手小白,总是用比较暴力的方法来解决问题,导致做了很多多余的步骤,下面给出我的超时的解法:

private class node{
            public int start;
            public int end;
            public int length;
            public node(int a,int b,int c){
                start = a;
                end = b;
                length = c;
            }
    }
    public int lengthOfLongestSubstring(String s) {
            node maxResult = new node(0, 0, 0);
            node max = new node(0,0,0);
            int i=0;
            ArrayList<Character> cl = new ArrayList<Character>();
            HashMap<Character, Integer> hMap = new HashMap<Character, Integer>();
            while(i<s.length()){
                System.out.println("循环开始 ,i ="+i);
                if(cl.isEmpty()){
                    max.start = i;
                    System.out.println("开始坐标:"+i);
                    cl.add(s.charAt(i));
                    i++;
                    continue;
                }

                if(!cl.contains(s.charAt(i))){

                    cl.add(s.charAt(i));
                    System.out.println(cl);
                    i++;
                }
                else {

                    System.out.println("结尾:"+i+", 因为有了:"+s.charAt(i));
                    max.end = i-1;
                    max.length = max.end - max.start+1;
                    if(max.length>maxResult.length)
                    {
                        maxResult.start = max.start;
                        maxResult.end = max.end;
                        maxResult.length = max.length;
                    }
                    i = s.indexOf(s.charAt(i), max.start)+1;
                    max = new node(0,0,0);
                    cl = new ArrayList<Character>();
                    if(maxResult.end>=s.length())
                        break;
                }
            }
            return maxResult.length;
    }

这是一个O(n^2)的算法,因为重复检验了中间本没重复字符的子串导致一个n的代价。
下面给出改进后的算法

public class Solution {

    public int lengthOfLongestSubstring(String s) {
            int max_len = 0;
            int index = 0;
            int start = 0;
            int cur_len = 0;
            HashMap<Character, Integer> map= new HashMap<Character, Integer>();
            while(index<=s.length()){
            //如果长度为0
                if(s.length()==0)
                    return 0;
            //到字符串的结尾的时候
                if(index==s.length())
                {
            //将算出来的cur_len与最大的比较
                    if(cur_len>max_len)
                        max_len = cur_len;
                    break;
            //跳出循环
                }
                //没有包含扫描到的字符
                if(!map.containsKey(s.charAt(index))){
                //长度自加
                    cur_len++;
                    //将该字符放到map中
                    map.put(s.charAt(index), index);
                    //递增遍历变量
                    index++;

                }
                //如果map中有该字符的记录
                else
                {
                //如果是在start左边则为无效记录,更新map记录
                    if(map.get(s.charAt(index))<start)
                    {
                        map.put(s.charAt(index), index);
                        cur_len++;
                    }
                    //该字符在子串中重复
                    else{
                        start = map.get(s.charAt(index))+1;
                        map.put(s.charAt(index), index);
                        if(cur_len>max_len)
                            max_len = cur_len;
                        cur_len = index-start+1;
                    }

                    index++;
                }
            }
            return max_len;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值