没有重复字符的最长子串

给定一个字符串,在不重复字符的情况下找出最长子字符串的长度。
例如,没有重复字母“abcabcbb”的最长子字符串是“abc”,长度为3。
对于“bbbbb”,最长的子字符串是“b”,长度为1。

  1. 用一个集合存放当前子串,循环遍历字符串中的字符
  2. 如果当前集合不包含当前字符,就将其加入集合。并对最长子串的最长长度进行更新
  3. 如果包含,就需要将该字符第一次出现的前面的所有字符从集合里删除。
  4. 直到循环结束。

这里自己实现的代码在做第三个步骤的时候,很复杂,然后看了一个别人做的,顿时觉得。。。。

这里很巧妙的使用了一个指针 i ,来实现第三个步骤。利用 i 指针来记录子串开始的位置,然后这样删除的时候就从 i 删除到 第一次重复 字符出现的后一位置;

public int lengthOfLongestSubstring(String s) {
    int i = 0, j = 0, max = 0;
    Set<Character> set = new HashSet<>();
    
    while (j < s.length()) {
        if (!set.contains(s.charAt(j))) {
            set.add(s.charAt(j++));
            max = Math.max(max, set.size());
        } else {
            set.remove(s.charAt(i++));
        }
    }
    
    return max;
}

使用一个map 加上 指针i 和 j 相对于 set集合 减少 删除集合中元素的操作,用一个map 来存放 键值(字符,位置)。不断更新。

public int lengthOfLongestSubstring(String s) {
    int ret = 0;
    Map<Character, Integer> map = new HashMap<>();
    for (int i = 0, start = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (map.containsKey(c)) 
        	// 对 窗口起始位置的更新,注意这里是取位置 c 和 start 的最大值
            start = Math.max(map.get(c)+1, start);
        ret = Math.max(ret, i-start+1); 
        // 更新 字符 c 的位置或者加入字符 c 或者他的位置
        map.put(c, i);
    }
    return ret;
}

而自己这部分的代码就是没有吃透删除部分,而是用了一个String 来存放当前子串,进行子串的更新。

import java.util.*;
public class Solution {
    public int lengthOfLongestSubstring(String s) {
        if (s == null)
            return 0;
        int len = 0;
        Set<String> str = new HashSet<>();
        String string = "";
        for (int i = 0; i < s.length(); i++) {
            String cur = s.substring(i, i+1);
            if (str.contains(cur)) {
                int curIndex = string.indexOf(cur);
                String rm = string.substring(0, curIndex + 1);
                string = string.substring(curIndex + 1);
                if (str.size() > len) {
                    len = str.size();
                }
                for (int j = 0; j < rm.length(); j++) {
                    str.remove(rm.substring(j, j+ 1));
                }
                str.add(cur);
                string = string + cur;
            } else {
                str.add(cur);
                string += cur;
                if (str.size() > len) len = str.size();
            }            
        }
        return len;
    }
}

其实这就是个滑动窗口,i 到 j 之间为窗口的大小,而 i 到 j 的窗口内部没有重复的字符。如果 j 出发生重复,那么 i 就需要到 重复字符第一次出现的下一个位置。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值