无重复字符的最长子串-算法

文章介绍了三种方法解决给定字符串中找到无重复字符的最长子串问题:动态规划的Java实现,滑动窗口策略,以及使用哈希集合记录模式的方法。通过对比分析,展示了如何利用这些技术来找出最长连续子串。
摘要由CSDN通过智能技术生成

题目

给定一个字符串,给出其中无重复字符的最长子串长度

解题

记录每个字符的下标最大值,再往后遍历的过程中判断是否已有该字符记录,如果有表示有重复,则在i到j中间为可能最长子串。如果排除子串的问题呢?通过双指针,一个快,一个慢,快指针循环往后遍历,慢指针根据是否与慢指针相同字符的位置做位移。因此可以排除掉子串的问题

比如i=5,j=10的位置都是a,但其中有i1=7,j2=8的位置都是b,那么5~10必然不能取。那么在快指针向后移动经过8位置时,判断7位置是重复字符,则将慢指针更新到8位置,就不会有上面的那种情况。

//利用动态规划的思想
public int findMaxSubStringWithoutDuplicateChar(String source){
  int start = 0;
  int end = 0;
  int res = 0;
  Map<Character, Integer> charMaxIndexMap = new HashMap<>();
  while (end < source.length()) {
    char endChar = source.charAt(end);
    if (charMaxIndexMap.containsKey(endChar)) {
      start = Math.max(start, charMaxIndexMap.get(endChar) + 1);
      res = Math.max(res, end - start + 1);
    } else {
      res = Math.max(res, end - start + 1);
    }
    charMaxIndexMap.put(endChar, end);
    end++;
  }
  return res;
}

//滑动窗口
public static int getLongestSubStringWithWindow(String source) {
  if(source==null||source.length()==0){
    return 0;
  }
  Set<Character> window = new HashSet<>();
  int slow = 0;
  int fast = 1;
  int result = 1;
  int length = source.length();
  window.add(source.charAt(slow));
  while (fast < length) {
    if (window.add(source.charAt(fast))) {
      fast++;
    } else {
      while (source.charAt(slow) != source.charAt(fast)) {
        window.remove(source.charAt(slow));
        slow++;
      }
      window.remove(source.charAt(slow));
      slow++;
    }
    result = Math.max(result, fast - slow);
  }
  return result;
}

//地图记录模式,逐步更新已走过的字符,然后用于当前最右字符
public static int getLongestSubStringOfWalked(String source) {
  int length = source.length();
  int left = 0;
  int right = 0;
  int result = 0;
  boolean[] walkedRecord = new boolean[256];
  while (right < length) {
    int curChar = (int)source.charAt(right);
    while (left < right && walkedRecord[curChar]) {
      walkedRecord[(int)source.charAt(left++)] = false;
    }
    walkedRecord[curChar] = true;
    result = Math.max(result, right - left + 1);
    right++;
  }
  return result;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慢一点,细一点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值