一、LeetCode介绍
LeetCode是一个在线编程网站,提供各种算法和数据结构的题目,面向程序员、计算机科学专业学生和技术爱好者等人群,旨在帮助他们提高算法和编程技能。LeetCode上的问题通常来自各种技术公司的面试题目,因此它也是程序员面试准备的重要资源之一。
LeetCode上的问题涵盖了各种难度级别,从入门级到专家级都有不同难度的题目可供练习。用户可以选择使用不同的编程语言提交答案,LeetCode能够对结果进行评估并返回测试结果。
除了题目外,LeetCode还提供了讨论区、排行榜等社区功能,用户可以在这里交流学习心得、解决疑难问题,并与其他用户比较自己的做题成绩。
挑战100天 AI In LeetCode是基于LeetCode题库,借助AI的能力进行解题、并学习其解题过程。
二、LeetCode 热题 HOT 100-3
2.1 题目
无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2: 输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 示例 3: 输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 提示: 0 <= s.length <= 5 * 104 s 由英文字母、数字、符号和空格组成
2.2 题解
时间复杂度为 O(n),其中 n 是字符串的长度。
解题思路:
这道题可以通过使用滑动窗口来解决,滑动窗口是一种在数组或字符串上进行迭代的算法,该技术可以将嵌套的循环问题转换为线性时间问题,从而降低时间复杂度。
具体来说,我们可以定义一个窗口,用于表示当前的子串。在每一步的操作中,我们会将左端点向右移动一格,并尝试拓展右端点,如果当前子串中不存在重复字符,则将右端点继续向右移动,直到出现重复字符为止。此时,我们找到的不含重复字符的子串就是以左端点开始的最长子串。
具体实现时,我们可以使用一个哈希集合存储当前子串中的字符,保证查询和删除的时间复杂度均为 O(1)。在移动右端点时,如果发现当前字符已经存在于哈希集合中,则将左端点向右移动,直到重复的字符从当前子串中移除为止。每次移动左端点时,从哈希集合中删除对应的字符,以此保证其后仍然是一个不含重复字符的子串。
public int lengthOfLongestSubstring(String s) { if (s == null || s.length() == 0) { return 0; } int maxLength = 0; Set<Character> set = new HashSet<>(); int left = 0, right = 0; while (right < s.length()) { if (!set.contains(s.charAt(right))) { set.add(s.charAt(right)); maxLength = Math.max(maxLength, set.size()); right++; } else { set.remove(s.charAt(left)); left++; } } return maxLength; }
三、面试经典 150 题-3
数组 / 字符串
3.1 题目
删除有序数组中的重复项
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过: 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。 返回 k 。 判题标准: 系统会用下面的代码来测试你的题解: int[] nums = [...]; // 输入数组 int[] expectedNums = [...]; // 长度正确的期望答案 int k = removeDuplicates(nums); // 调用 assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; } 如果所有断言都通过,那么您的题解将被 通过。 示例 1: 输入:nums = [1,1,2] 输出:2, nums = [1,2,_] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。 示例 2: 输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。 提示: 1 <= nums.length <= 3 * 104 -104 <= nums[i] <= 104 nums 已按 非严格递增 排列
3.2 题解
时间复杂度为 O(n),其中 n 是数组的长度。空间复杂度为 O(1)。
解题思路:
代码中使用了双指针的思想,通过一个指针 i 来指示当前不重复元素的位置。遍历数组时,如果遇到不同的元素,就将该元素放到 i 的位置,并将 i 后移一位,从而实现原地删除重复元素的功能。
- 初始化一个指针 i,初始值为 0,表示当前不重复元素的位置。
- 遍历数组,从索引 1 开始:
- 如果当前元素与前一个元素相同,说明出现了重复元素,跳过该元素。
- 如果当前元素与前一个元素不同,将当前元素覆盖到指针 i 的位置,并将指针 i 向前移动一位。
- 返回指针 i 的值,即为新数组的长度。
public int removeDuplicates(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int i = 0; for (int j = 1; j < nums.length; j++) { if (nums[j] != nums[i]) { i++; nums[i] = nums[j]; } } return i + 1; }
至此,挑战100天 AI In LeetCode Day02(1)完成,后续会持续调整;查阅过程中若遇到问题欢迎留言或私信交流。