《剑指offer—面试题48:最长不含重复字符的子字符串》

《剑指offer—面试题48:最长不含重复字符的子字符串》
注明:仅个人学习笔记

方法一参考:https://blog.csdn.net/qq_28618765/article/details/65627503
方法二参考:https://blog.csdn.net/m0_37862405/article/details/80369128

import java.util.HashMap;
import java.util.Map;

/**
*
*
* 最长不含重复字符的子字符串 如在字符串”arabcacfr”,其中最长不含重复字符的子字符串是“acfr”
*
*/
public class LongestSubstringWithoutDuplication48
{

public int lengthOfLongestSubstring(String s)
{
    // 字符串输入不合法
    if (s == null)
    {
        return 0;
    }

    // 当前处理的开始位置
    int start = 0;
    // 记录到的最大非重复子串长度
    int result = 0;
    // 访问标记,记录最新一次访问的字符和位置
    Map<Character, Integer> map = new HashMap<>(s.length());

    for (int i = 0; i < s.length(); i++)
    {
        char ch = s.charAt(i);//得到当前遍历的字符

        // 如果遍历的当前字符之前出现过,且上一次出现的位置大于等于子串起始位置,也就是说该字符上一次出现时在子串中
        // 如果字符已经出现过(在标记开位置算起),就重新标记start
        if (map.containsKey(ch) && map.get(ch) >= start)
        {
            start = map.get(ch) + 1;// 此时,子串的起始位置更新为,从当前字符上一次出现时的下一个字符开始
        }
        // 如果没有出现过就求最大的非重复子串的长度
        else
        {
            // 如果当前没出现过或者说是没有出现在以start开始的子串中,那就意味着直接加上当前字符,更新子串长
            //更新最大非重复子字符串的长度
            result = Math.max(result, i - start + 1);
        }

        // 更新访问记录
        map.put(ch, i);// 更新当前字符出现的位置
    }
    return result;
}

private static int findLongestSubstringLength(String string)
{

    if (string == null || string.equals(""))
        return 0;

    int maxLength = 0;
    int curLength = 0;

    // positions 用来保存每个字符上次出现在字符串中位置的下标
    int[] positions = new int[26];// 用于记录当前字符上一次出现的位置
    for (int i = 0; i < positions.length; i++)
    {
        positions[i] = -1; // 初始化为-1,负数表示没出现过
    }

    for (int i = 0; i < string.length(); i++)
    {

        // 判断遍历时,当前字符的合法性
        if (!(string.charAt(i) >= 'a' && string.charAt(i) <= 'z'))
        {
            System.err.println("error!! ---Invalid input!!");
            return 0;
        }

        // 这里做一个转换,一是同样可以表示当前字符,二是同时作为保存字符出现位置的数组的索引;
        // 索引即使代表的某一字符,其数组值代表出现的位置;和用hashmap一样,那个里面是key代表字符,value代表字符出现的位置
        int curChar = string.charAt(i) - 'a';// 当前字符是哪一个
        int prePosition = positions[curChar];// 当前一字符上一次出现的位置
        // 当前字符与它上次出现位置之间的距离
        int distance = i - prePosition;

        // 当前字符第一次出现,或者前一个非重复子字符串中没有包含当前字符
        if (prePosition < 0 || distance > curLength)
        {
            curLength++;
        } else
        {
            // 更新最长非重复子字符串的长度//这部分不去更新maxLength也可以
            if (curLength > maxLength)
            {
                maxLength = curLength;
            }
            curLength = distance;
        }
        positions[curChar] = i; // 更新字符出现的位置
    }

    if (curLength > maxLength)
    {
        maxLength = curLength;
    }
    return maxLength;
}

public static void main(String[] args)
{
    int i = findLongestSubstringLength("arab");

    System.out.println(i);
}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值