Loading

求字符串中最长无重复字符子串长度问题

求字符串中最长无重复字符子串长度问题

作者:Grey

原文地址:

博客园:求字符串中最长无重复字符子串长度问题

CSDN:求字符串中最长无重复字符子串长度问题

题目描述

题目链接

思路

假设必须以i位置字符结尾的字符串最大不重复字串的长度是x,那么所有位置x值中最大的值就是答案。

i位置的x的值取决于两个因素。

第一个因素是i-1向左边能扩到最左位置(即:i-1位置上的x值)。

第二个因素是i位置的值上一次出现的位置。

这两个因素取最大值即可算出i位置的x的值。

比如

[b,c,1,a,a,x,3,4,b,4]

这个字符串,我们要求必须以第4个位置a这个字符结尾的字符串最大不重复子串的长度是多少?

此时:i=4

先看上面说的第一个因素:i-1位置(即3号位置上的a)能向左边扩到的最左位置是0位置(赋给变量mostLeft),

第二个因素:i位置的a字符上一次出现的位置是3位置(赋给变量prePos),

所以i位置的x值就是:

i - max(mostLeft, prePos) = 4 - max(0, 3) = 4 - 3 = 1

示例图如下

示例1

image

示例2

image

如何记录i位置上一次出现的位置呢?

可以用一个整型数组arr来表示,因为字符串由英文字母、数字、符号和空格组成,所以arr的长度设置为256即可,arr中每个位置的初始值都是-1,在遍历到i号字符的时候,设置arr[str[i]]=i,即记录了i号位置字符的位置信息,a字符的ascii码是97, 那么arr[97] = 3,表示a字符上次出现的位置是3。

如何记录i向左扩能扩到最左的位置是哪里?

可以用一个mostLeft变量来记录,mostLeft初始是-1,在遍历字符串的过程中,mostLefti字符上一次出现的位置决策出的最大值,即为i位置能扩的最左位置。

完整代码

import java.util.Arrays;

public class LeetCode_0003_LongestSubstringWithoutRepeatingCharacters {
    public static int lengthOfLongestSubstring(String s) {
        if (s == null) {
            return 0;
        }
        char[] str = s.toCharArray();
        if (str.length <= 1) {
            return str.length;
        }
        int n = str.length;
        int[] arr = new int[256];
        // 默认每个位置的字符上一次出现的位置都是-1
        Arrays.fill(arr, -1);
        int max = 1;
        int mostLeft = -1;
        for (int i = 0; i < n; i++) {
            // i位置的字符上一次出现的位置
            int prePos = arr[str[i]];
   // i-1能扩到的最左侧位置和prePos决策出当前i位置能扩的最左侧位置
            mostLeft = Math.max(prePos, mostLeft);
   // 和全局max对比,抓到最大值
            max = Math.max(max, i - mostLeft);
            // i号位置的字符的位置信息记录在arr中
            arr[str[i]] = i;
        }
        return max;
    }
}

更多

算法和数据结构笔记

posted @ 2021-04-15 12:29  Grey Zeng  阅读(306)  评论(0编辑  收藏  举报