楼主: Myron2017
跳转到指定楼层
上一主题 下一主题
收起左侧

刷题记录帖子

🔗
 楼主| Myron2017 2026-4-13 08:10:29 | 只看该作者
全局:
LC. 3894. Traffic Signal Color

简单题。
  1. class Solution:
  2.     def trafficSignal(self, timer: int) -> str:
  3.         if timer == 0: return "Green"
  4.         elif timer == 30: return "Orange"
  5.         elif timer > 30 and timer <= 90: return "Red"
  6.         else:
  7.             return "Invalid"
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-14 08:35:53 | 只看该作者
全局:
LC.3895. Count Digit Appearances

String Solution
  1. class Solution:
  2.     def countDigitOccurrences(self, nums: list[int], digit: int) -> int:
  3.         d = str(digit)
  4.         ans = 0

  5.         for num in nums:
  6.             ans += str(num).count(d)
  7.         
  8.         return ans

  9.         
复制代码
No-String Solution
  1. class Solution:
  2.     def countDigitOccurrences(self, nums: list[int], digit: int) -> int:
  3.         ans = 0
  4.         
  5.         for num in nums:
  6.             # We use a while loop to check each digit from right to left
  7.             while num > 0:
  8.                 # Check if the last digit matches the target digit
  9.                 if num % 10 == digit:
  10.                     ans += 1
  11.                 # Remove the last digit
  12.                 num //= 10
  13.                
  14.         return ans
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-14 08:44:26 | 只看该作者
全局:
LC. 3896. Minimum Operations to Transform Array into Alternating Prime
  1. class Solution:
  2.     def minOperations(self, nums: list[int]) -> int:
  3.         # 1. 确定搜索范围:nums[i] 最大 10^5,需要稍微多预留一点空间找下一个素数
  4.         LIMIT = 100003 + 10  # 100003 是 10^5 之后第一个素数
  5.         is_prime = [True] * LIMIT
  6.         is_prime[0] = is_prime[1] = False
  7.         
  8.         # 埃氏筛预处理
  9.         for p in range(2, int(LIMIT**0.5) + 1):
  10.             if is_prime[p]:
  11.                 for i in range(p * p, LIMIT, p):
  12.                     is_prime[i] = False
  13.         
  14.         # 2. 收集所有素数,方便用二分法(或直接从 is_prime 查找)
  15.         primes = [i for i, val in enumerate(is_prime) if val]
  16.         
  17.         import bisect
  18.         
  19.         ans = 0
  20.         for idx, val in enumerate(nums):
  21.             if idx % 2 == 0:
  22.                 # 偶数下标 -> 需要素数
  23.                 if not is_prime[val]:
  24.                     # 寻找第一个大于等于 val 的素数
  25.                     # bisect_left 在有序列表中找到插入位置
  26.                     pos = bisect.bisect_left(primes, val)
  27.                     ans += (primes[pos] - val)
  28.             else:
  29.                 # 奇数下标 -> 需要非素数
  30.                 if is_prime[val]:
  31.                     # 如果当前是素数,必须变大。最小的非素数变化通常是 +1
  32.                     # 比如 2 变 4 (2->3也是素数), 3 变 4, 5 变 6
  33.                     # 唯一需要注意的是,所有素数 +1 之后一定是非素数吗?
  34.                     # 除了素数 2 变 3 还是素数外,其他素数都是奇数,+1 变偶数一定是合数。
  35.                     # 所以:如果 val 是 2,变到下一个非素数是 4(步数 2);
  36.                     # 如果 val > 2,变到下一个非素数就是 val + 1(步数 1)。
  37.                     if val == 2:
  38.                         ans += 2
  39.                     else:
  40.                         ans += 1
  41.                         
  42.         return ans
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-15 09:58:33 | 只看该作者
全局:
LC . 2515. Shortest Distance to Target String in a Circular Array

虽然是简单题,但是还是可以优化。

我做的预处理完全没有必要,当然当时做的时候没想到。还是要学习一个!
  1. class Solution:
  2.     def closestTarget(self, words: List[str], target: str, startIndex: int) -> int:
  3.         w_index = defaultdict(list)
  4.         n = len(words)

  5.         for ind, val in enumerate(words):
  6.             w_index[val].append(ind)

  7.         if target not in w_index:
  8.             return -1
  9.         else:
  10.             ans = float('inf')
  11.             for i in w_index[target]:
  12.                 d1 = abs(startIndex - i)
  13.                 ans = min(ans, d1, n - d1)
  14.             return ans


  15.         
复制代码
优化 code
  1. class Solution:
  2.     def closestTarget(self, words: List[str], target: str, startIndex: int) -> int:
  3.         n = len(words)
  4.         res = n  # 初始化为一个不可能达到的最大步数
  5.         
  6.         for i in range(n):
  7.             if words[i] == target:
  8.                 # 直接距离
  9.                 dist = abs(i - startIndex)
  10.                 # 比较:当前步数 vs 顺时针步数 vs 逆时针步数
  11.                 # n - dist 即为绕一圈回来的另一种走法
  12.                 res = min(res, dist, n - dist)
  13.         
  14.         return res if res < n else -1
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-15 22:42:25 | 只看该作者
全局:
LC 3663. Find The Least Frequent Digit

简单题,但是可以优化代码。

我的答案
  1. class Solution:
  2.     def getLeastFrequentDigit(self, n: int) -> int:
  3.         freq = defaultdict(int)

  4.         for c in str(n):
  5.             freq[int(c)] += 1


  6.         f = []
  7.         for k, v in freq.items():
  8.             f.append(v)
  9.         ans = min(f)
  10.         key = sorted(freq.keys())

  11.         for k in key:
  12.             if freq[k] == ans:
  13.                 return k
  14.         
复制代码
可以用 Counter 统计频率。
先找了最小频率 ans,又排序了 keys,再循环找结果。其实可以在一次遍历或排序中搞定。

优化代码
  1. class Solution:
  2.     def getLeastFrequentDigit(self, n: int) -> int:
  3.         # 1. 统计频率:Counter 会帮你把 '1553322' 变成 {'5':2, '3':2, '2':2, '1':1}
  4.         freq = Counter(str(n))
  5.         
  6.         # 2. 找到最小的出现次数
  7.         min_freq = min(freq.values())
  8.         
  9.         # 3. 找出所有满足最小次数的数字,转成 int 以便排序
  10.         candidates = [int(digit) for digit, count in freq.items() if count == min_freq]
  11.         
  12.         # 4. 返回其中最小的数字
  13.         return min(candidates)


  14.         
复制代码
也可以利用元组排序
  1. class Solution:
  2.     def getLeastFrequentDigit(self, n: int) -> int:
  3.         from collections import Counter
  4.         
  5.         counts = Counter(str(n))
  6.         
  7.         # 我们把字典项转成 (频率, 数字) 的列表
  8.         # 注意:这里数字要转成 int,否则 '10' 会排在 '2' 前面(字符串排序 vs 数字排序)
  9.         items = []
  10.         for digit, freq in counts.items():
  11.             items.append((freq, int(digit)))
  12.             
  13.         # 默认升序:先按频率升序,频率相同按数字升序
  14.         # 排序后的第一个元素就是我们要的
  15.         items.sort()
  16.         
  17.         return items[0][1]


  18.         
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-16 10:17:54 | 只看该作者
全局:
3662. Filter Characters by Frequency
Solved
Easy
Topics
Hint
You are given a string s consisting of lowercase English letters and an integer k.

Your task is to construct a new string that contains only those characters from s which appear fewer than k times in the entire string. The order of characters in the new string must be the same as their order in s.

Return the resulting string. If no characters qualify, return an empty string.

Note: Every occurrence of a character that occurs fewer than k times is kept.



Example 1:

Input: s = "aadbbcccca", k = 3

Output: "dbb"

Explanation:

Character frequencies in s:

'a' appears 3 times
'd' appears 1 time
'b' appears 2 times
'c' appears 4 times
Only 'd' and 'b' appear fewer than 3 times. Preserving their order, the result is "dbb".

Example 2:

Input: s = "xyz", k = 2

Output: "xyz"

Explanation:

All characters ('x', 'y', 'z') appear exactly once, which is fewer than 2. Thus the whole string is returned.



Constraints:

1 <= s.length <= 100
s consists of lowercase English letters.
1 <= k <= s.length
  1. from collections import Counter

  2. class Solution:
  3.     def filterCharacters(self, s: str, k: int) -> str:
  4.         # 第一遍:统计频率
  5.         freq = Counter(s)
  6.         ans = []

  7.         # 第二遍:根据频率过滤,同时利用 list 维持顺序
  8.         for ch in s:
  9.             if freq[ch] < k:
  10.                 ans.append(ch)
  11.         
  12.         # 最后合并成字符串,比 += 字符串性能更好
  13.         return "".join(ans)
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-16 11:02:18 | 只看该作者
全局:
LC 3488. Closest Equal Element Queries

这道题(LC 3488)虽然被标记为 Medium,但它是理解搜索空间压缩和环形结构建模的绝佳案例。通过这道题,你可以沉淀以下四个核心维度的知识:1. 搜索空间的“极度压缩”这是本题最高级的直觉:在有序集合中,最近的元素一定是相邻的。启发: 当题目要求寻找“最近”、“最小差值”时,如果能把候选索引提取出来并排序,你的搜索范围就从“整个数组”缩减到了“左右邻居”。通用模型: 以后遇到“找同类中最近的”,第一反应应该是:哈希表存下标列表 + 二分查找邻居。2. 环形数组(Circular Array)的两种处理套路环形数组是面试常客,这道题涵盖了环形结构的两个层面:物理层面的环(索引): 如何在列表首尾实现“无缝对接”?技巧: 使用取模运算 % m。它能优雅地把 0 的左边变成 m-1,把 m-1 的右边变成 0。这比写一堆 if-else 判断边界要专业得多。逻辑层面的环(距离): 两个点 $i$ 和 $j$ 在长度为 $n$ 的环上的距离。公式: $dist = \min(|i - j|, n - |i - j|)$。理解: 一个是“直接走”的距离,一个是“绕一圈”的距离。3. 从 $O(\log N)$ 到 $O(1)$ 的优化思维在解决这道题的过程中,我们经历了三种复杂度的演进:暴力解法 $O(Q \times N)$: 遍历所有相同数字。二分优化 $O(Q \log N)$: 利用 bisect 在有序下标中定位。完全预处理 $O(Q)$: 通过一个 idx_to_pos 数组提前存好每个索引在 v_list 里的位置。收获: 只要查询次数 $Q$ 足够大,任何能通过空间换时间省掉的 $\log N$ 都是值得的。在面试中,主动提出从 $O(\log N)$ 优化到 $O(1)$ 会非常加分。4. 易错点与防御性编程索引 vs 元素: 你在之前的 debug 中犯的错误(用 pos 减 q)非常典型。要时刻提醒自己:我现在操作的是“列表的索引”还是“原数组的索引”?特例处理: 这种找“另一个”元素的问题,必须优先检查 len(v_list) == 1 的情况,避免死循环或无效计算。


raw code
  1. class Solution:
  2.     def solveQueries(self, nums: List[int], queries: List[int]) -> List[int]:
  3.         valIndDict = defaultdict(list)
  4.         for ind, val in enumerate(nums):
  5.             valIndDict[val].append(ind)
  6.         
  7.         ans = []
  8.         n = len(nums)

  9.         for q in queries:
  10.             v = nums[q]
  11.             if len(valIndDict[v]) == 1:
  12.                 ans.append(-1)
  13.             else:
  14.                 # has multiple v
  15.                 v_list = valIndDict[v]
  16.                 pos = bisect.bisect_left(v_list, q)
  17.                 m = len(v_list)

  18.                 minD = float('inf')
  19.                 for k in [ v_list[(pos+1)%m], v_list[(pos-1)%m] ]:
  20.                         minD = min(minD, abs(k - q), n - abs(k-q))
  21.                 ans.append(minD)
  22.             
  23.         return ans
  24.         
复制代码
优化后代码
  1. from collections import defaultdict
  2. import bisect
  3. from typing import List

  4. class Solution:
  5.     def solveQueries(self, nums: List[int], queries: List[int]) -> List[int]:
  6.         n = len(nums)
  7.         # 1. 预处理:记录每个值对应的所有下标
  8.         val_to_indices = defaultdict(list)
  9.         # 2. 预处理:记录每个原数组下标 i 在它对应的 indices 列表里的位置(排名)
  10.         idx_to_pos = [0] * n
  11.         
  12.         for i, v in enumerate(nums):
  13.             idx_to_pos[i] = len(val_to_indices[v])
  14.             val_to_indices[v].append(i)
  15.             
  16.         ans = []
  17.         for q in queries:
  18.             v = nums[q]
  19.             v_list = val_to_indices[v]
  20.             m = len(v_list)
  21.             
  22.             if m == 1:
  23.                 ans.append(-1)
  24.                 continue
  25.             
  26.             # 直接通过预处理的数组拿到排名,省去 bisect_left 的 O(log N)
  27.             pos = idx_to_pos[q]
  28.             
  29.             # 只检查左右邻居(含环形首尾)
  30.             res = float('inf')
  31.             # 这里的 k 是 v_list 里的元素,即原数组的下标
  32.             for k in [v_list[(pos - 1) % m], v_list[(pos + 1) % m]]:
  33.                 diff = abs(k - q)
  34.                 # 环形距离公式
  35.                 dist = min(diff, n - diff)
  36.                 if dist < res:
  37.                     res = dist
  38.             ans.append(res)
  39.             
  40.         return ans
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-17 08:50:00 | 只看该作者
全局:
LC. 3658. GCD of Odd and Even Sums

简单题,但是考察了辗转相除法,不搜索下我也忘记了。。。

还是要提高自己的知识水平!
  1. class Solution:
  2.     def gcdOfOddEvenSums(self, n: int) -> int:
  3.         sumOdd, sumEven = n * n, (n+1) * n

  4.         def GCD(a, b):
  5.             if b > a: a, b = b, a
  6.             r = a % b
  7.             if r == 0: return b
  8.             else:
  9.                 return GCD(b, r)

  10.         return GCD(sumOdd, sumEven)


  11.         
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-17 09:29:56 | 只看该作者
全局:
LC 3761. Minimum Absolute Distance Between Mirror Pairs

虽然过了但是还是有很多可以优化的地方。
  1. class Solution:
  2.     def minMirrorPairDistance(self, nums: List[int]) -> int:
  3.         n = len(nums)
  4.         val_ind_dict = defaultdict(list)

  5.         for ind,val in enumerate(nums):
  6.             val_ind_dict[val].append(ind)
  7.         ans = float('inf')
  8.         for ind,num in enumerate(nums):
  9.             s_num = str(num)
  10.             start = len(s_num) - 1
  11.             while s_num[start] == '0':
  12.                 start -= 1

  13.             reversed_s_num = s_num[start::-1]


  14.             if int(reversed_s_num) in val_ind_dict:
  15.                 pos = bisect.bisect_left(val_ind_dict[int(reversed_s_num)], ind)

  16.                 m = len(val_ind_dict[int(reversed_s_num)])
  17.                 pos_list = [pos+1, pos-1, pos]
  18.                 for p in pos_list:
  19.                     if p >= 0 and p < m and val_ind_dict[int(reversed_s_num)][p] > ind:
  20.                         print(val_ind_dict[int(reversed_s_num)][p])
  21.                         ans = min(ans, abs(val_ind_dict[int(reversed_s_num)][p]-ind))

  22.         if ans == float('inf'):
  23.             return -1
  24.         else:
  25.             return ans

  26.         
复制代码
做的时候,我已经发现了 i < j 了,其实这个就带来了单调性。但是当时没有深入思考, 其实这就是说明,你如果 让 i 从 右向左走,只需要考虑右边的已经看到的最近的 reversed 之后数的 index 就行了,我这个是考虑没有 i < j 的方案。

一次遍历:时间复杂度由 $O(N \log N)$ 降到了 $O(N)$(假设整数长度固定,字符串转换是常数级)。空间优化:last_seen 只存一个整数下标,而不是下标列表,空间更省。面试加分:利用“逆向遍历”解决“寻找右侧最近”的问题,是非常经典的面试套路,展示了你对数组题目深厚的理解。
  1. class Solution:
  2.     def minMirrorPairDistance(self, nums: List[int]) -> int:
  3.         # last_seen 记录数字 x 在当前位置右侧“最近”出现的下标
  4.         last_seen = {}
  5.         min_dist = float('inf')
  6.         n = len(nums)
  7.         
  8.         # 从右往左遍历,这样当我们遇到 nums[i] 时,
  9.         # last_seen 里存的都是 i 之后的下标 j
  10.         for i in range(n - 1, -1, -1):
  11.             num = nums[i]
  12.             
  13.             # 1. 核心逻辑:计算当前数字反转后的目标值
  14.             # int(str(num)[::-1]) 会自动处理 120 -> "021" -> 21 的逻辑
  15.             target = int(str(num)[::-1])
  16.             
  17.             # 2. 如果目标值在右边出现过,更新最小距离
  18.             if target in last_seen:
  19.                 dist = last_seen[target] - i
  20.                 if dist < min_dist:
  21.                     min_dist = dist
  22.             
  23.             # 3. 记录/更新当前数字出现的位置
  24.             # 因为是从右往左,这里记录的是该数字目前为止最靠左(离左边最近)的位置
  25.             last_seen[num] = i
  26.             
  27.         return min_dist if min_dist != float('inf') else -1

  28.         
复制代码
当然有个小语法的地方也要注意,如何在 Python 中翻转字符串。

回复

使用道具 举报

🔗
 楼主| Myron2017 2026-4-18 10:15:38 | 只看该作者
全局:
LC 3633. Earliest Finish Time for Land and Water Rides I

简单题,但是还是可以优化。

我的解法,暴力 loop
  1. class Solution:
  2.     def earliestFinishTime(self, landStartTime: List[int], landDuration: List[int], waterStartTime: List[int], waterDuration: List[int]) -> int:
  3.         ans = float('inf')

  4.         for ls, ld in zip(landStartTime, landDuration):
  5.             for ws, wd in zip(waterStartTime, waterDuration):
  6.                 if ws <= (ls+ld):
  7.                     ans = min(ans, ls+ld+wd)
  8.                 else:
  9.                     ans = min(ans, ws+wd)

  10.         for ws, wd in zip(waterStartTime, waterDuration):
  11.             for ls, ld in zip(landStartTime, landDuration):
  12.                 if ls <= (ws+wd):
  13.                     ans = min(ans, ws+wd+ld)
  14.                 else:
  15.                     ans = min(ans, ls+ld)


  16.         return ans
复制代码
但是,其实不用可以贪心,无论陆地还是水面,你都挑选最早结束那个项目作为第一个项目一定是不亏的。
然后剩下就是 best-land 和 best-water 对后面分别接 water 还是 land 循环。

复杂度一下子从 O(N x M). == > O(N + M)
  1. from typing import List

  2. class Solution:
  3.     def earliestFinishTime(self, landStartTime: List[int], landDuration: List[int], waterStartTime: List[int], waterDuration: List[int]) -> int:
  4.         # 1. 预处理:找到最早结束的陆地项目和最早结束的水上项目
  5.         # 因为无论你选哪个作为第一项,结束时间越早,对第二项越有利。
  6.         best_land_end = min(s + d for s, d in zip(landStartTime, landDuration))
  7.         best_water_end = min(s + d for s, d in zip(waterStartTime, waterDuration))
  8.         
  9.         ans = float('inf')
  10.         
  11.         # 2. 情况一:先陆后水
  12.         # 我们已经知道陆地最快在 best_land_end 结束
  13.         # 那么对于所有的水上项目,我们选一个能让我们最快结束的
  14.         for ws, wd in zip(waterStartTime, waterDuration):
  15.             # 结束时间 = max(第一项结束时间, 第二项开始时间) + 第二项持续时间
  16.             finish_time = max(best_land_end, ws) + wd
  17.             if finish_time < ans:
  18.                 ans = finish_time
  19.                
  20.         # 3. 情况二:先水后陆
  21.         for ls, ld in zip(landStartTime, landDuration):
  22.             finish_time = max(best_water_end, ls) + ld
  23.             if finish_time < ans:
  24.                 ans = finish_time
  25.                
  26.         return ans
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表