算法思路练习001-无重复字符的最长子串

题目

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

思路-错误

使用双指针,在一个for循环里遍历,fast指针在前遍历字符串,low指针暂时待在起点,当char[fast] = char[low],说明出现重复字符,此时保存一下fast-low的长度,即当前获取到的一个不含重复字符的子串长度。

问题

fast向前移动过程中,low指针和fast指针中间可能会有重复字符。
比如abcbb
low指向a,fast往后移动时,char[low]==char[fast]始终不成立,但是有相同字符。

错误代码

//错误代码
void lengthOfChildString(Stirng s){{
            if (s.length() < 2) {
                return s.length();
            }
            char[] c = s.toCharArray();
            int fast = 1;
            int low = 0;
            int result = 0;
            while (fast < s.length()) {
                if (c[fast] == c[low]) {
                    result = result > (fast - low) ? result : (fast - low);
                    low++;
                } else {
                    fast++;
                }
            }
            return result > (fast - low) ? result : (fast - low);
        }

}

正确思路-使用map构建滑动窗口容器

map.containsKey()可以准确的判断出当前容器中是否含有遍历到的字符。
按照字符串顺序遍历到某个数的时候:
如果map中没有当前数,则直接放入map,容器大小+1
如果map中有当前数,则获取到已存在值的kv,把已存在的值包括之前的值全部移出map。或者将计算长度的左下标移动到刚刚匹配到的重复的字符下一个位置处。

代码

void lengthOfChildString(Stirng s){
            //用作存储字符的容器
            HashMap<Character,Integer> map = new HashMap<>();
//            LinkList<Character> ll = new LinkedList<Character>();

            //发现重复字符后移动的指针
            int left = 0;
            int result = 0;
            for (int i = 0; i < s.length(); i++) {
                //判断map滑动窗口中是否含有当前遍历的字符
                if (map.containsKey(s.charAt(i))) {
                    //如果有,就把left指针往前移动。
                    left = left > (map.get(s.charAt(i))+1) ? left : (map.get(s.charAt(i))+1);
                    //i    2 3 4 5   6 7
                    //left 0 1 2 3   3 3
                }
                //else {
                    map.put(s.charAt(i), i);//a0,b1,c2,
                //}
                result = Math.max(result,i - left+1);//3 3 3 3    4 5
            }
            return result;

        }

注意

滑动窗口移动过程中,每个元素都要插入。
注意上面注释掉的else{},如果判断map中有相同元素就不插入的话就会使下一次left的移动失败。left获取的还是前面重复字符的位置,导致出错,结果变大。
没有更新map中最新字符坐标,导致left原地不动,出现错误结果

希望我永远都拥有开始的勇气。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值