LeetCode 831. Masking Personal Information
题目描述给你一条个人信息字符串 s,可能表示一个邮箱地址,也可能表示一串电话号码。按照以下规则对个人信息进行隐藏/加密处理: 邮箱地址规则: 所有字母转为小写。 保留邮箱名的第一个字符和 @ 之前最后一个字符,中间用 "*****" 替换。 域名保持不变。 举例:"LeetCode@LeetCode.com" → "l*****e@leetcode.com" 电话号码规则: 处理前 10-13 位数字的电话号码。 手机号码格式为 "***-***-XXXX"(10 位)。 带有国家代码时,国家代码的每一位用 "+" 开头,每一位用 "*" 代替(除最后一位外),如 11 位为 "+*-***-***-XXXX",12 位为 "+**-***-***-XXXX",13 位为 "+***-***-***-XXXX"。 输入可能包含 +、-、(、) 和空格等分隔符,需要先去除再做处理。 解题...
LeetCode 316. Remove Duplicate Letters
问题描述给你一个字符串 s,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。 解题思路本题的本质是:在保持原字符串中每个字符相对顺序的前提下,选出一个字典序最小的子序列,且每个字符恰好出现一次。这是经典的单调栈 + 贪心问题。 核心思路 统计每个字符的出现次数:用 count[26] 数组记录每个字符在剩余字符串中还剩多少个。这是判断”能否丢弃当前字符”的关键依据。 维护单调递增栈:遍历字符串,对于每个字符 c: 将 count[c] 减 1 如果 c 已经在栈中,跳过(确保每个字符只出现一次) 如果 c 不在栈中,检查栈顶字符 top: 如果 top > c(栈顶字符字典序大于当前字符)且 count[top] > 0(后续还会出现 top),则可以将 top 弹出。因为我们可以后面再添加 top,这样能让结果字典序更小 重复以上检查,直到栈为空或栈顶不能再弹出 将 c 压入栈 结果输出:栈中从底到顶就是最终结果的逆序,反转后得到答案。 举例说明以输入 s = "bcabc&...
LeetCode 66. Plus One
题目描述给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位,数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。 解题思路这道题模拟的是整数加一的过程。由于数组中每个元素只存储单个数字,我们需要从最低位(数组末尾)开始处理进位。 核心思路如下: 从数组的最低位(digits.length - 1)向最高位(下标 0)遍历: 如果当前位小于 9,直接加一并返回结果(因为不会有进位,后面的高位无需处理)。 如果当前位等于 9,将其置为 0,并继续向前一位处理进位。 如果遍历完整个数组后仍然没有返回(即所有位都是 9,例如 999),说明需要进位到更高的位。此时创建一个比原数组长一位的新数组,将首位设为 1,其余位默认为 0,即得到了结果(例如 1000)。 这个解法的巧妙之处在于: 利用”遇到小于 9 直接返回”的提前终止策略,避免了不必要的遍历 只有在全为 9 的极端情况下才需要扩容数组 复杂度分析 时间复杂度:O(n),其中 n 是数组长度。最坏情况下需要遍历整个数组(所有位都是 9)。 空间复杂度:...
LeetCode 941. Valid Mountain Array
题目描述给定一个整数数组 arr,如果它是有效的山脉数组就返回 true,否则返回 false。 有效山脉数组的定义: arr.length >= 3 存在某个下标 i(0 < i < arr.length - 1)使得: arr[0] < arr[1] < ... < arr[i-1] < arr[i] arr[i] > arr[i+1] > ... > arr[arr.length - 1] 即数组先严格递增,到某个峰值后严格递减。峰值不能在数组的首尾位置。 例如: arr = [0,3,2,1] → true(峰值 3 在下标 1) arr = [3,5,5] → false(有相等元素,不是严格递增/递减) arr = [0,1,2,3] → false(只有递增,没有递减) 解题思路本题可以用线性扫描(类似双指针的思想)一次遍历解决。 算法步骤 如果数组长度小于 3,直接返回 false(不满足山峰的最短长度要求)。 第一阶段:爬坡(递增段扫描) 从下标 0 开始向右遍历,只要 arr...
LeetCode 1470. Shuffle the Array
题目描述给你一个数组 nums,数组中有 2n 个元素,按 [x1, x2, ..., xn, y1, y2, ..., yn] 的格式排列。请你将数组按 [x1, y1, x2, y2, ..., xn, yn] 格式重新排列,返回重排后的数组。 示例 1: 123输入:nums = [2,5,1,3,4,7], n = 3输出:[2,3,5,4,1,7]解释:x1=2, x2=5, x3=1, y1=3, y2=4, y3=7,重排后为 [2,3,5,4,1,7] 示例 2: 12输入:nums = [1,2,3,4,4,3,2,1], n = 4输出:[1,4,2,3,3,2,4,1] 解题思路题目要求将数组从”前半部分 x + 后半部分 y”的排列方式转换为”交叉排列”的方式。换句话说,原数组的前 n 个元素是 x 组,后 n 个元素是 y 组,我们需要逐一交叉取出。 分析步骤: 数组长度为 2n,前 n 个元素 nums[0] 到 nums[n-1] 对应 x1 到 xn。 后 n 个元素 nums[n] 到 nums[2n-1] 对应 y1 到 yn。 目标顺序...
LeetCode 1929. Concatenation of Array
题目描述给你一个长度为 n 的整数数组 nums。请你构建一个长度为 2n 的答案数组 ans,ans 由两个 nums 数组串联形成。形式化地,ans[i] == nums[i] 且 ans[i + n] == nums[i](0 <= i < n)。返回数组 ans。 示例 1: 12输入:nums = [1,2,1]输出:[1,2,1,1,2,1] 示例 2: 12输入:nums = [1,3,2,1]输出:[1,3,2,1,1,3,2,1] 解题思路本题要求将原数组与自己拼接一次,核心是构造一个长度为 2n 的新数组,其中前 n 个元素与原数组完全相同,后 n 个元素也是原数组的副本。 在 Python 中,列表的 + 运算符本身就是序列拼接操作,它会创建一个新的列表对象,其中包含左侧列表的全部元素,随后紧接右侧列表的全部元素。这与题目要求的”串联”语义完全一致。 分析步骤: nums 是一个包含 n 个元素的整数列表。 表达式 nums + nums 将 nums 与自身拼接,结果是一个长度为 2n 的新列表。 对于任意索引 i(0 <= i &...
LeetCode 485. Max Consecutive Ones
题目描述给定一个二进制数组 nums,计算其中最大连续 1 的个数。 示例 1: 123输入:nums = [1,1,0,1,1,1]输出:3解释:开头的两位和末尾的三位都是连续 1,所以最大连续 1 的个数是 3。 示例 2: 12输入:nums = [1,0,1,1,0,1]输出:2 解题思路本题要求找出二进制数组中最长的一段连续 1 的长度。核心思想是遍历数组并维护两个变量:当前连续 1 的长度(pre_sum)和全局最大连续 1 的长度(max_sum)。 算法分析步骤: 初始化 pre_sum = 0(当前连续 1 的长度)和 max_sum = 0(全局最大值)。 遍历数组中的每个元素 nums[i]: 尝试将当前元素累加到 pre_sum 上,计算结果 res = pre_sum + nums[i]。 关键判断: 如果 res == pre_sum,说明 nums[i] == 0(累加后值不变,即遇到 0)。此时: 用当前的 pre_sum(即上一个连续 1 段的长度)更新 max_sum。 将 pre_sum 重置为 0,开始下一段计数。 否则(res ...
LeetCode 1365. How Many Numbers Are Smaller Than the Current Number
题目描述给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。以数组形式返回答案。 例如:nums = [8,1,2,2,3],输出 [4,0,1,1,3]。 解释:对于 nums[0]=8,存在四个比它小的数字(1,2,2,3);对于 nums[1]=1,没有比它小的数字;对于 nums[2]=2,存在一个比它小的数字(1);以此类推。 解题思路暴力法最直接的想法是对于每个元素,遍历整个数组统计比它小的元素个数,时间复杂度 O(n²)。当数据量较大时效率很低。 排序 + 哈希表(O(n log n))本题的关键观察是:当我们把数组排序后,每个元素在排序数组中的下标,恰好就等于比它小的元素个数(因为排序后前面全是小于等于它的元素)。 具体步骤: 克隆并排序:将原数组 nums 克隆到 nums2,然后对 nums2 进行排序。 建立映射:遍历排序后的数组,建立”元素值 → 最小下标”的映射。注意处理重复元素——对于重复元素,应取第一次出现的位置(即最小的下标),因为比它小的元素个数应该是排序后第一个该值出现的下标。 使用 map.put...
LeetCode 1441. Build an Array With Stack Operations
题目描述给你一个目标数组 target 和一个整数 n。每次迭代,需要从 list = {1,2,3...,n} 中读取一个数字。使用栈操作 Push 和 Pop,构建目标数组 target。返回构建 target 所用的操作序列。 例如:target = [1,3],n = 3,输出 ["Push","Push","Pop","Push"]。 解释:读取 1,Push(得到 [1]);读取 2,Push(得到 [1,2]),但 2 不在 target 中,所以 Pop(得到 [1]);读取 3,Push(得到 [1,3]),3 在 target 中。 解题思路核心思想题目本质是一个模拟问题。我们按顺序从 1 到 n 遍历数字,对于每个数字 i: 无论 i 是否在 target 中,我们都需要先执行 Push。 如果 i 不在 target 中,则紧接着执行 Pop(相当于 Push 之后马上 Pop 掉)。 如果 i 在 target 中,则保留,继续处理下一个数字。 当 target 中的所有数...
LeetCode 1470. Shuffle the Array
题目描述给你一个数组 nums,数组中有 2n 个元素,按 [x1,x2,...,xn,y1,y2,...,yn] 的格式排列。请你将数组按 [x1,y1,x2,y2,...,xn,yn] 格式重新排列,返回重排后的数组。 例如:nums = [2,5,1,3,4,7],n = 3,输出 [2,3,5,4,1,7]。 解释:x1=2, x2=5, x3=1,y1=3, y2=4, y3=7,交错排列得 [2,3,5,4,1,7]。 解题思路核心思想这是一个数组重排问题,本质是双指针或交错填充。给定 n,我们知道: x 部分的元素在 nums[0] 到 nums[n-1]。 y 部分的元素在 nums[n] 到 nums[2n-1]。 目标是将两个部分交错:x1, y1, x2, y2, ..., xn, yn。 步骤 创建结果数组 ans,长度为 2n。 使用指针 i 在结果数组中填充,使用指针 j 遍历 x 部分和 y 部分: 每次迭代,先放入 nums[j](来自 x 部分),然后放入 nums[j + n](来自 y 部分)。 j 从 0 到 n-1。 示例以 n...