LeetCode 2073. Time Needed to Buy Tickets
题目描述有 n 个人前来排队买票,其中第 0 人站在队伍最前方,第 n-1 人站在队伍最后方。给定一个整数数组 tickets,其中 tickets[i] 表示第 i 个人想要购买的票数。每个人买票需要 1 秒。一个人一次只能买一张票,买完后如果还需要买更多票,就必须走到队尾重新排队。返回位于位置 k 的人完成买票所需的时间。 例如:tickets = [2,3,2],k = 2,输出 6。 解释:排队的模拟过程为: 第 1 秒:第 0 人买一张,剩余 [1,3,2],到队尾。 第 2 秒:第 1 人买一张,剩余 [1,2,2],到队尾。 第 3 秒:第 2 人(k=2)买一张,剩余 [1,2,1],到队尾。 第 4 秒:第 0 人买一张,剩余 [0,2,1],离队。 第 5 秒:第 1 人买一张,剩余 [0,1,1],到队尾。 第 6 秒:第 2 人买最后一张,剩余 [0,1,0],完成。所需时间为 6 秒。 解题思路模拟法(代码所用方法)直接按照题目描述的规则进行模拟。 步骤 初始化计数器 ans = 0,使用无限循环和取模运算模拟环形队列。 在循环中 inde...
LeetCode 232. Implement Queue using Stacks
问题描述请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty)。使用自定义的 MyQueue 类(位于 datastructure 包中),内部用两个栈实现队列。 解题思路栈是后进先出(LIFO)的数据结构,队列是先进先出(FIFO)的数据结构。要用栈模拟队列,关键在于两次入栈等于一次顺序反转。 双栈设计使用两个栈: 输入栈(stackIn):专门负责接收 push 操作 输出栈(stackOut):专门负责 pop 和 peek 操作 核心操作原理 push(x):直接将元素压入 stackIn。时间复杂度 O(1)。 pop() / peek(): 如果 stackOut 不为空,直接从 stackOut 弹出/查看栈顶元素 如果 stackOut 为空,则将 stackIn 中的所有元素依次弹出并压入 stackOut。经过这次转移,stackIn 中的元素顺序被反转,stackOut 的栈顶恰好就是整个队列的队首元素 empty():当两个栈都为空时,队列为空。 为什么这样做是正确...
LeetCode 482. License Key Formatting
问题描述给定一个许可密钥字符串 s,仅由字母、数字字符和破折号组成。字符串由 n 个破折号分成 n+1 组。给定一个整数 k,重新格式化字符串,使每一组恰好包含 k 个字符,第一组可以少于 k 个字符但至少包含一个字符。用破折号分隔组,所有小写字母转换为大写。 解题思路本题的要点在于理解分组规则:除了第一组外,其余每组恰好 k 个字符。这意味着我们需要先计算出总的有效字符数,然后确定第一组的大小。 算法步骤 去除破折号: 使用 s.split("-") 将原字符串按破折号分割 将所有非破折号部分拼接起来,得到所有有效字符的连续字符串 计算第一组长度: 设总有效字符数为 sumLength 第一组的长度 firstLen = sumLength % k 如果 firstLen == 0(恰好整除),则第一组也应取 k 个字符 按组格式化: 取前 firstLen 个字符作为第一组,转为大写 从 firstLen 位置开始,每次取 k 个字符作为一组,组间用 "-" 分隔,每组转为大写 举例说明示例 1:s = "...
LeetCode 520. Detect Capital
问题描述我们定义,在以下情况时,单词的大写用法是正确的: 全部字母都是大写,比如 "USA" 单词中所有字母都不是大写,比如 "leetcode" 如果单词不只含有一个字母,只有首字母大写,比如 "Google" 给定一个字符串 word,判断其大写使用是否正确。 解题思路题目的三种合法情况可以归纳为三个独立的判断条件,满足其一即可: 辅助方法设计 isAllUppercase(str):检查字符串中所有字符是否都是大写 遍历每个字符,如果发现小写字母则返回 false isAllLowercase(str):检查字符串中所有字符是否都是小写 遍历每个字符,如果发现大写字母则返回 false isFirstUppercase(str):检查是否首字母大写且其余字母小写 先检查首字母是否大写 如果是,从第二个字符开始遍历,发现大写字母则返回 false 如果首字母不是大写,直接返回 false 主逻辑1return isAllLowercase(word) || isFirstUppercase(w...
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 &...