剑指 Offer 48. 最长不含重复字符的子字符串(3. 无重复字符的最长子串)

题目:

思路:

【1】这道题不难,暴力破解也是可以的,但是双循环带来的开销无疑很大的。所以以空间换时间借助辅助空间,那么就要思考辅助空间怎么知道该字符已经被收录了,如数据结构中的contains函数,判断是否在数据结构里面。但是换个角度想想,每个字符其实都是有对应的ASCII码,也就是有表可看,那么其实可以构建一个固定的数组,用于标记这些,boolean也可,int也行,但是int消耗更小,比较一个8字节,一个4字节,消耗更小的内存做一样的事。

代码展示:

遍历加队列的处理方法

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //创建队列
        Queue<Character> queue = new LinkedList<>();
        int max = 0;
        for (char c : s.toCharArray()) {
            while (queue.contains(c)) {
                //如果有重复的,队头出队,直到没有重复的为止
                queue.poll();
            }
            //添加到队尾
            queue.add(c);
            //更新max
            max = Math.max(max, queue.size());
        }
        return max;
    }
}

 

双指针加辅助空间:

//时间2 ms击败96.65%
//内存41.4 MB击败68.60%
//时间复杂度为O(N),因为最优情况下是右指针走一遍,最差的情况是左右指针都走一遍,其实也就是遍历个数最多为2N
//空间复杂度为O(1),因为开辟的是固定常量的辅助空间
//思路采用双指针+int数组辅助空间
//双指针是为了拉长之后计算距离
//int数组用于记录你是否扫描过该字符,因为在英文中字符是有ASCII表参考的
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int[] tag = new int[256];
        int left = 0, right = 0, count = 0;
        while (right < s.length()){
            if (tag[s.charAt(right)] == 0){
                tag[s.charAt(right++)] = 1;
                count = Math.max(count,(right - left));
            }else {
                tag[s.charAt(left++)] = 0;
            }
        }

        return count;
    }
}

 

posted @ 2023-08-04 15:57  忧愁的chafry  阅读(11)  评论(0编辑  收藏  举报