LeetCode3. Longest Substring Without Repeating Characters

题目

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given “abcabcbb”, the answer is “abc”, which the length is 3.

Given “bbbbb”, the answer is “b”, with the length of 1.

Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

找出一个字符串的不含有重复字符的最长子串,注意,子串需要连续而子序列不需要。

解题思路

这题的思路很明显是动态规划,O(n^2)的方法很容易想到,即用一个bool类型的二维数组表示一个子串是否是非重复子串,然后一路递推就可以,但这明显不是我们想要的。
可不可以一次便利得出结果?可以

public int lengthOfLongestSubstring(String s) {
        //指向正在遍历的字母的指针
        int start = 0;
        int end = -1;
        //指向最长的子串的开头结尾的指针
        int resStart = 0;
        int resEnd = -1;
        //指向上一个子串的指针
        int tmpStart = 0;
        int tmpEnd = -1;
        //用来存储不重复的字符,值表示字符所在位置
        HashMap<Character, Integer> set = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            //如果发现字符重复,进行一系列操作
            if (set.containsKey(s.charAt(i))) {
                //先保留这个子串,方便map删除
                tmpStart = start;
                tmpEnd = end;
                //如果正在遍历的子串长度大于之前的最大值,就替换
                if (end - start + 1 >= resEnd - resStart + 1) {
                    resStart = start;
                    resEnd = end;
                }
                //重新设置开始值为重复的字符的下一位
                start = set.get(s.charAt(i)) + 1;
                end = i;

                //如果与前一位相同,直接清空map
                if (s.charAt(i) == s.charAt(i - 1))
                    set.clear();
                else {
                    //否则仅清空相同位之前的字符
                    int index = set.get(s.charAt(i));
                    for (int k = tmpStart; k <= index; k++) {
                        set.remove(s.charAt(k));
                    }
                }
            } else {
                //不重复,直接向后遍历
                end++;
            }
            //把不重复的字符加入map
            set.put(s.charAt(i), i);
        }
        //因为存在最后一位字符所在的子串刚好是最长的可能,而这时又不会触发上方的语句,所以需要在结尾加个判断
        return resEnd - resStart + 1 > end - start + 1 ? resEnd - resStart + 1 : end - start + 1;
    }
在准备 LeetCode 面试题时,一些高频题目和经典题型是必须掌握的,这些题目覆盖了数组、字符串、链表、树、动态规划等多个方面。以下是一些常见的 LeetCode 面试题: ### 数组与双指针类问题 - **LeetCode 160. Intersection of Two Linked Lists**:判断两个链表是否相交,并找到交点。 - **LeetCode 141. Linked List Cycle**:判断链表中是否存在环。 - **LeetCode 92. Reverse Linked List II**:反转链表的指定部分。 - **LeetCode 328. Odd Even Linked List**:将链表中的奇偶节点分开并连接到一起。 - **LeetCode 面试题 16.06. 最小差**:找到两个数组中差值最小的两个数,常用双指针法解决[^4]。 ### 字符串与哈希类问题 - **LeetCode 242. Valid Anagram**:判断两个字符串是否是变位词,通常使用哈希表或数组统计字符频率来解决[^2]。 - **LeetCode 1. Two Sum**:在数组中找出两个数使其和等于目标值,常用哈希表存储差值。 - **LeetCode 49. Group Anagrams**:将变位词分组,常用于哈希表处理字符串特征。 ### 链表类问题 - **LeetCode 2. Add Two Numbers**:两个链表表示的数字相加,需要考虑进位问题。 - **LeetCode 21. Merge Two Sorted Lists**:合并两个有序链表。 - **LeetCode 234. Palindrome Linked List**:判断链表是否是回文结构,可以使用快慢指针和反转链表结合的方法[^1]。 ### 树与图类问题 - **LeetCode 104. Maximum Depth of Binary Tree**:计算二叉树的最大深度。 - **LeetCode 102. Binary Tree Level Order Traversal**:二叉树的层序遍历。 - **LeetCode 236. Lowest Common Ancestor of a Binary Tree**:找到二叉树的最近公共祖先。 ### 排列组合与回溯类问题 - **LeetCode 面试题 08.08. 有重复字符串的排列组合**:给出有重复字符串的所有排列组合,通常使用回溯法实现[^5]。 - **LeetCode 46. Permutations**:生成不重复数字的所有排列。 - **LeetCode 78. Subsets**:生成一个数组的所有子集。 ### 动态规划类问题 - **LeetCode 70. Climbing Stairs**:爬楼梯问题,动态规划入门题。 - **LeetCode 198. House Robber**:打家劫舍问题,典型的线性动态规划。 - **LeetCode 322. Coin Change**:找零钱的最小硬币数,典型的完全背包问题。 ### 高频经典题 - **LeetCode 3. Longest Substring Without Repeating Characters**:无重复字符的最长子串,滑动窗口法的经典应用[^3]。 - **LeetCode 5. Longest Palindromic Substring**:最长回文子串,扩展中心法或动态规划解决。 - **LeetCode 8. String to Integer (atoi)**:字符串转换为整数,需考虑各种边界条件。 ### 代码示例 以下是一个判断两个字符串是否互为变位词的 Java 示例代码: ```java class Solution { public boolean isAnagram(String s, String t) { if (s.length() != t.length()) return false; int[] num = new int[26]; for (int i = 0; i < s.length(); i++) { num[s.charAt(i) - &#39;a&#39;]++; num[t.charAt(i) - &#39;a&#39;]--; } for (int i : num) { if (i != 0) return false; } return true; } } ``` ### 进阶建议 在准备 LeetCode 面试题时,不仅要掌握这些高频题目,还要理解其背后的数据结构和算法思想,例如快慢指针、双指针、滑动窗口、动态规划等。此外,代码实现要熟练,尤其是链表反转、字符串处理、数组操作等基础操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值