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

刷题记录帖子

🔗
 楼主| Myron2017 2026-9-8 09:56:41 | 只看该作者
全局:
4044. Count Good Cyclic Rotations

You are given an integer array nums of even length n.

A cyclic rotation of nums is obtained by choosing a prefix of nums whose length is between 0 and n - 1 (inclusive), and moving it to the end of the array while preserving the order of all elements.

A cyclic rotation is good if the sum of its first n / 2 elements is strictly greater than the sum of its last n / 2 elements.

Return the number of cyclic rotations of nums that are good.



Example 1:

Input: nums = [1,2,3,4,5,6]

Output: 3

Explanation:

The cyclic rotations of nums are:

Cyclic rotation        Sum of first n / 2 elements        Sum of last n / 2 elements
[1, 2, 3, 4, 5, 6]        1 + 2 + 3 = 6        4 + 5 + 6 = 15
[2, 3, 4, 5, 6, 1]        2 + 3 + 4 = 9        5 + 6 + 1 = 12
[3, 4, 5, 6, 1, 2]        3 + 4 + 5 = 12        6 + 1 + 2 = 9
[4, 5, 6, 1, 2, 3]        4 + 5 + 6 = 15        1 + 2 + 3 = 6
[5, 6, 1, 2, 3, 4]        5 + 6 + 1 = 12        2 + 3 + 4 = 9
[6, 1, 2, 3, 4, 5]        6 + 1 + 2 = 9        3 + 4 + 5 = 12
The first half has a greater sum than the second half for 3 rotations. Thus, the answer is 3.

Example 2:

Input: nums = [1,2,1,2]

Output: 0

Explanation:

The cyclic rotations of nums are:

Cyclic rotation        Sum of first n / 2 elements        Sum of last n / 2 elements
[1, 2, 1, 2]        1 + 2 = 3        1 + 2 = 3
[2, 1, 2, 1]        2 + 1 = 3        2 + 1 = 3
[1, 2, 1, 2]        1 + 2 = 3        1 + 2 = 3
[2, 1, 2, 1]        2 + 1 = 3        2 + 1 = 3
No cyclic rotation is good because the two sums are equal for every rotation. Thus, the answer is 0.



Constraints:

2 <= n == nums.length <= 105
1 <= nums[i] <= 109
n is even.

我的解法 -- 滑动窗口 (Sliding Window), 其实这里的数学推导非常漂亮:对于前半部分 $s_1$:向右滑动一位时,抛弃了最左边的 nums[i-1],迎来了新加入 $s_1$ 末尾的 nums[i + half - 1]。对于后半部分 $s_2$:抛弃了原本 $s_2$ 最左边的元素(即 nums[i + half - 1]),迎来了新加入 $s_2$ 末尾的元素(即整体旋转后被挪到最右边的原 nums[i-1])。因为你做了一步 nums = nums + nums,所以最右边新进来的元素下标恰好对应的值就是 nums[i-1]。
  1. class Solution:
  2.     def countGoodRotations(self, nums: list[int]) -> int:
  3.         ans = 0
  4.         n = len(nums)
  5.         nums = nums + nums
  6.         half = n // 2
  7.         s1, s2 = 0, 0

  8.         for i in range(n):
  9.             if i < half:
  10.                 s1 += nums[i]
  11.             else:
  12.                 s2 += nums[i]

  13.         if s1 > s2: ans += 1

  14.         for i in range(1, n):
  15.             s1 -= nums[i-1]
  16.             s1 += nums[i+half-1]
  17.             s2 += nums[i-1]
  18.             s2 -= nums[i+half-1]

  19.             if s1 > s2: ans += 1
  20.         
  21.         return ans
复制代码
优化 -- 数学不变量 (Invariant) 来把代码写得更加精炼。

破题核心:总和是不变的 (Total Sum Invariant)无论数组怎么循环旋转,数组里所有的元素本质上没有变,只是位置换了。这意味着:整个数组的总和 $S = s_1 + s_2$ 是一个恒定不变的常数!既然 $s_2 = S - s1$,那么题目要求的条件 $s_1 > s_2$ 就可以做等价变形:$$s_1 > S - s1 \iff 2 \cdot s_1 > S$$结论:我们完全不需要维护 $s_2$!只需要维护一个长度为 $n/2$ 的滑动窗口 $s_1$,每次判断 $2 \cdot s_1 > S$ 是否成立即可。

利用这个性质,我们可以省去对 $s_2$ 的一切加减操作,让滑动窗口代码变得极简:
  1. class Solution:
  2.     def countGoodRotations(self, nums: list[int]) -> int:
  3.         n = len(nums)
  4.         half = n // 2
  5.         total_sum = sum(nums)  # 整个数组的总和(不变量)
  6.         
  7.         # 1. 计算初始 rotation (i = 0) 的 s1
  8.         s1 = sum(nums[:half])
  9.         
  10.         ans = 1 if 2 * s1 > total_sum else 0
  11.         
  12.         # 2. 拼接数组避免取模运算(空间换时间,极佳的工程实践)
  13.         nums_ext = nums + nums
  14.         
  15.         # 3. 滑动窗口:只维护 s1 即可
  16.         for i in range(1, n):
  17.             # s1 移出旧元素 nums_ext[i-1],移入新元素 nums_ext[i + half - 1]
  18.             s1 += nums_ext[i + half - 1] - nums_ext[i - 1]
  19.             
  20.             if 2 * s1 > total_sum:
  21.                 ans += 1
  22.                
  23.         return ans
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-9 09:10:33 | 只看该作者
全局:
LC. 2678. Number of Senior Citizens

简单题,轻松秒杀
  1. class Solution:
  2.     def countSeniors(self, details: List[str]) -> int:
  3.         ans = 0
  4.         for detail in details:
  5.             if int(detail[11:13]) > 60:
  6.                 ans += 1
  7.         return ans
复制代码
改进


1. Pythonic 一行流(生成器表达式 + sum)
在 Python 中,布尔值 True 隐式等于 1,False 等于 0:
  1. class Solution:
  2.     def countSeniors(self, details: List[str]) -> int:
  3.         return sum(int(d[11:13]) > 60 for d in details)
复制代码
2. 利用 ASCII 字符比较(省去 int() 转型的开销)因为年龄固定是两位数(即 $00 \sim 99$),在 ASCII 字典序中,数字字符串的大小比较与对应的数值大小比较是完全等价的!例如 "75" > "60" 的结果就是 True。
  1. class Solution:
  2.     def countSeniors(self, details: List[str]) -> int:
  3.         return sum(d[11:13] > "60" for d in details)
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-10 09:49:31 | 只看该作者
全局:
2677. Chunk Array
Solved
Easy
conpanies icon
Companies
Given an array arr and a chunk size size, return a chunked array.

A chunked array contains the original elements in arr, but consists of subarrays each of length size. The length of the last subarray may be less than size if arr.length is not evenly divisible by size.

Please solve it without using lodash's _.chunk function.



Example 1:

Input: arr = [1,2,3,4,5], size = 1
Output: [[1],[2],[3],[4],[5]]
Explanation: The arr has been split into subarrays each with 1 element.
Example 2:

Input: arr = [1,9,6,3,2], size = 3
Output: [[1,9,6],[3,2]]
Explanation: The arr has been split into subarrays with 3 elements. However, only two elements are left for the 2nd subarray.
Example 3:

Input: arr = [8,5,3,2,6], size = 6
Output: [[8,5,3,2,6]]
Explanation: Size is greater than arr.length thus all elements are in the first subarray.
Example 4:

Input: arr = [], size = 1
Output: []
Explanation: There are no elements to be chunked so an empty array is returned.


Constraints:

arr is a string representing the array.
2 <= arr.length <= 105
1 <= size <= arr.length + 1
  1. type JSONValue = null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue };
  2. type Obj = Record<string, JSONValue> | Array<JSONValue>;

  3. function chunk(arr: Obj[], size: number): Obj[][] {
  4.     const chunked: Obj[][] = [];
  5.    
  6.     for (let i = 0; i < arr.length; i += size) {
  7.         chunked.push(arr.slice(i, i + size));
  8.     }
  9.    
  10.     return chunked;

  11. };
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-11 10:49:48 | 只看该作者
全局:
LC. 2670. Find the Distinct Difference Array
Solved
Easy
Topics
Hint
You are given a 0-indexed array nums of length n.

The distinct difference array of nums is an array diff of length n such that diff[i] is equal to the number of distinct elements in the suffix nums[i + 1, ..., n - 1] subtracted from the number of distinct elements in the prefix nums[0, ..., i].

Return the distinct difference array of nums.

Note that nums[i, ..., j] denotes the subarray of nums starting at index i and ending at index j inclusive. Particularly, if i > j then nums[i, ..., j] denotes an empty subarray.



Example 1:

Input: nums = [1,2,3,4,5]
Output: [-3,-1,1,3,5]
Explanation: For index i = 0, there is 1 element in the prefix and 4 distinct elements in the suffix. Thus, diff[0] = 1 - 4 = -3.
For index i = 1, there are 2 distinct elements in the prefix and 3 distinct elements in the suffix. Thus, diff[1] = 2 - 3 = -1.
For index i = 2, there are 3 distinct elements in the prefix and 2 distinct elements in the suffix. Thus, diff[2] = 3 - 2 = 1.
For index i = 3, there are 4 distinct elements in the prefix and 1 distinct element in the suffix. Thus, diff[3] = 4 - 1 = 3.
For index i = 4, there are 5 distinct elements in the prefix and no elements in the suffix. Thus, diff[4] = 5 - 0 = 5.
Example 2:

Input: nums = [3,2,3,4,2]
Output: [-2,-1,0,2,3]
Explanation: For index i = 0, there is 1 element in the prefix and 3 distinct elements in the suffix. Thus, diff[0] = 1 - 3 = -2.
For index i = 1, there are 2 distinct elements in the prefix and 3 distinct elements in the suffix. Thus, diff[1] = 2 - 3 = -1.
For index i = 2, there are 2 distinct elements in the prefix and 2 distinct elements in the suffix. Thus, diff[2] = 2 - 2 = 0.
For index i = 3, there are 3 distinct elements in the prefix and 1 distinct element in the suffix. Thus, diff[3] = 3 - 1 = 2.
For index i = 4, there are 3 distinct elements in the prefix and no elements in the suffix. Thus, diff[4] = 3 - 0 = 3.


Constraints:

1 <= n == nums.length <= 50
1 <= nums[i] <= 50

我的解法
  1. class Solution:
  2.     def distinctDifferenceArray(self, nums: List[int]) -> List[int]:
  3.         freq = Counter(nums)
  4.         diff = []
  5.         set_to_i = set()

  6.         for num in nums:
  7.             freq[num] -= 1
  8.             if freq[num] == 0:
  9.                 del freq[num]
  10.             set_to_i.add(num)

  11.             diff.append(len(set_to_i) - len(freq))
  12.         
  13.         return diff
复制代码
解法 B:前后缀数组预处理(两遍扫描)
如果面试官不允许你在遍历中修改字典结构(del freq[num]),可以采用更经典的前后缀预处理思想(类似 LC 238)
  1. class Solution:
  2.     def distinctDifferenceArray(self, nums: List[int]) -> List[int]:
  3.         n = len(nums)
  4.         
  5.         # suf_distinct[i] 表示后缀 nums[i...] 的不同元素个数
  6.         suf_distinct = [0] * (n + 1)
  7.         suf_set = set()
  8.         for i in range(n - 1, -1, -1):
  9.             suf_set.add(nums[i])
  10.             suf_distinct[i] = len(suf_set)
  11.             
  12.         res = []
  13.         pref_set = set()
  14.         for i in range(n):
  15.             pref_set.add(nums[i])
  16.             # 前缀 nums[0...i] 的不同元素数 - 后缀 nums[i+1...] 的不同元素数
  17.             res.append(len(pref_set) - suf_distinct[i + 1])
  18.             
  19.         return res
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-11 10:54:43 | 只看该作者
全局:
LC. 238. Product of Array Except Self
Solved
Medium
Topics
conpanies icon
Companies
Hint
Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].

The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

You must write an algorithm that runs in O(n) time and without using the division operation.



Example 1:

Input: nums = [1,2,3,4]
Output: [24,12,8,6]
Example 2:

Input: nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]


Constraints:

2 <= nums.length <= 105
-30 <= nums[i] <= 30
The input is generated such that answer[i] is guaranteed to fit in a 32-bit integer.


Follow up: Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)


解法
  1. class Solution:
  2.     def productExceptSelf(self, nums: List[int]) -> List[int]:

  3.         n = len(nums)
  4.         ans = [1] * (n)

  5.         for i in range(1, n):
  6.             ans[i] = ans[i - 1] * nums[i-1]

  7.         curr = nums[-1]

  8.         for i in range(n-2, -1, -1):
  9.             ans[i] = ans[i] * curr
  10.             curr *= nums[i]

  11.         return ans
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-11 11:00:21 | 只看该作者
全局:
LC. 2668. Find Latest Salaries
Solved
Easy
Topics
SQL Schema
Pandas Schema
Table: Salary

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| emp_id        | int     |
| firstname     | varchar |
| lastname      | varchar |
| salary        | varchar |
| department_id | varchar |
+---------------+---------+
(emp_id, salary) is the primary key (combination of columns with unique values) for this table.
Each row contains employees details and their yearly salaries, however, some of the records are old and contain outdated salary information.
Write a solution to find the current salary of each employee assuming that salaries increase each year. Output their emp_id, firstname, lastname, salary, and department_id.

Return the result table ordered by emp_id in ascending order.

The result format is in the following example.



Example 1:

Input:
Salary table:
+--------+-----------+----------+--------+---------------+
| emp_id | firstname | lastname | salary | department_id |
+--------+-----------+----------+--------+---------------+
| 1      | Todd      | Wilson   | 110000 | D1006         |
| 1      | Todd      | Wilson   | 106119 | D1006         |
| 2      | Justin    | Simon    | 128922 | D1005         |
| 2      | Justin    | Simon    | 130000 | D1005         |
| 3      | Kelly     | Rosario  | 42689  | D1002         |
| 4      | Patricia  | Powell   | 162825 | D1004         |
| 4      | Patricia  | Powell   | 170000 | D1004         |
| 5      | Sherry    | Golden   | 44101  | D1002         |
| 6      | Natasha   | Swanson  | 79632  | D1005         |
| 6      | Natasha   | Swanson  | 90000  | D1005         |
+--------+-----------+----------+--------+---------------+
Output:
+--------+-----------+----------+--------+---------------+
| emp_id | firstname | lastname | salary | department_id |
+--------+-----------+----------+--------+---------------+
| 1      | Todd      | Wilson   | 110000 | D1006         |
| 2      | Justin    | Simon    | 130000 | D1005         |
| 3      | Kelly     | Rosario  | 42689  | D1002         |
| 4      | Patricia  | Powell   | 170000 | D1004         |
| 5      | Sherry    | Golden   | 44101  | D1002         |
| 6      | Natasha   | Swanson  | 90000  | D1005         |
+--------+-----------+----------+--------+---------------+

Explanation:
- emp_id 1 has two records with a salary of 110000, 106119 out of these 110000 is an updated salary (Assuming salary is increasing each year)
- emp_id 2 has two records with a salary of 128922, 130000 out of these 130000 is an updated salary.
- emp_id 3 has only one salary record so that is already an updated salary.
- emp_id 4 has two records with a salary of 162825, 170000 out of these 170000 is an updated salary.
- emp_id 5 has only one salary record so that is already an updated salary.
- emp_id 6 has two records with a salary of 79632, 90000 out of these 90000 is an updated salary.
  1. # Write your MySQL query statement below
  2. select
  3. emp_id, firstname, lastname, max(salary) as salary, department_id
  4. from Salary
  5. group by emp_id
  6. order by emp_id


复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-11 11:01:48 | 只看该作者
全局:
LC. 2667. Create Hello World Function
Solved
Easy
conpanies icon
Companies
Write a function createHelloWorld. It should return a new function that always returns "Hello World".


Example 1:

Input: args = []
Output: "Hello World"
Explanation:
const f = createHelloWorld();
f(); // "Hello World"

The function returned by createHelloWorld should always return "Hello World".
Example 2:

Input: args = [{},null,42]
Output: "Hello World"
Explanation:
const f = createHelloWorld();
f({}, null, 42); // "Hello World"

Any arguments could be passed to the function but it should still always return "Hello World".


Constraints:

0 <= args.length <= 10
  1. function createHelloWorld() {
  2.    
  3.     return function(...args): string {
  4.         return "Hello World";
  5.     };
  6. };

  7. /**
  8. * const f = createHelloWorld();
  9. * f(); // "Hello World"
  10. */
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-12 09:39:37 来自APP | 只看该作者
全局:
LC. 2660. Determine the Winner of a Bowling Game
You are given two 0-indexed integer arrays player1 and player2, representing the number of pins that player 1 and player 2 hit in a bowling game, respectively.

The bowling game consists of n turns, and the number of pins in each turn is exactly 10.

Assume a player hits xi pins in the ith turn. The value of the ith turn for the player is:

2xi if the player hits 10 pins in either (i - 1)th or (i - 2)th turn.
Otherwise, it is xi.
The score of the player is the sum of the values of their n turns.

Return

1 if the score of player 1 is more than the score of player 2,
2 if the score of player 2 is more than the score of player 1, and
0 in case of a draw.


Example 1:

Input: player1 = [5,10,3,2], player2 = [6,5,7,3]

Output: 1

Explanation:

The score of player 1 is 5 + 10 + 2*3 + 2*2 = 25.

The score of player 2 is 6 + 5 + 7 + 3 = 21.

Example 2:

Input: player1 = [3,5,7,6], player2 = [8,10,10,2]

Output: 2

Explanation:

The score of player 1 is 3 + 5 + 7 + 6 = 21.

The score of player 2 is 8 + 10 + 2*10 + 2*2 = 42.

Example 3:

Input: player1 = [2,3], player2 = [4,1]

Output: 0

Explanation:

The score of player1 is 2 + 3 = 5.

The score of player2 is 4 + 1 = 5.

Example 4:

Input: player1 = [1,1,1,10,10,10,10], player2 = [10,10,10,10,1,1,1]

Output: 2

Explanation:

The score of player1 is 1 + 1 + 1 + 10 + 2*10 + 2*10 + 2*10 = 73.

The score of player2 is 10 + 2*10 + 2*10 + 2*10 + 2*1 + 2*1 + 1 = 75.



Constraints:

n == player1.length == player2.length
1 <= n <= 1000
0 <= player1[i], player2[i] <= 10

我的解法
  1. class Solution:
  2.     def isWinner(self, player1: List[int], player2: List[int]) -> int:
  3.         s1, s2 = 0, 0
  4.         n = len(player1)

  5.         for i in range(n):
  6.             
  7.             multiply1 = False
  8.             multiply2 = False
  9.             if i-1 >= 0:

  10.                 if player1[i-1] == 10: multiply1 = True
  11.                 if player2[i-1] == 10: multiply2 = True
  12.             if i-2 >= 0:

  13.                 if player1[i-2] == 10: multiply1 = True
  14.                 if player2[i-2] == 10: multiply2 = True
  15.             
  16.             if multiply1:
  17.                 s1 += player1[i] * 2
  18.             else:
  19.                 s1 += player1[i]

  20.             if multiply2:
  21.                 s2 += player2[i] * 2
  22.             else:
  23.                 s2 += player2[i]
  24.             
  25.         
  26.         
  27.         if s1 > s2: return 1
  28.         elif s2 > s1: return 2
  29.         else: return 0
复制代码
优化

我的写法核心思路是:对每个位置判断 i-1 和 i-2 是否为 10。

从两个角度进行优化:

提取公共函数(DRY 原则):避免针对 player1 和 player2 写两遍一模一样的计算代码。

状态追踪(更巧妙的索引更新):不需要每次都用 if 去查前一两格,只需要记录上一次击中 10 的轮次索引 last_ten。如果当前轮次 $i$ 距离上次击中 10 的距离 $i - last\_ten \le 2$,则直接翻倍。
  1. class Solution:

  2.     def isWinner(self, player1: list[int], player2: list[int]) -> int:
  3.         def calc_score(player: list[int]) -> int:
  4.             total = 0
  5.             last_ten = -10  # 初始设为负值,表示前面没有出现过 10

  6.             for i, x in enumerate(player):
  7.                 # 如果距离上一次击中 10 不超过 2 轮(即前一轮或前两轮)
  8.                 if i - last_ten <= 2:
  9.                     total += 2 * x
  10.                 else:
  11.                     total += x

  12.                 # 如果当前轮击中 10,更新最后一次出现 10 的位置
  13.                 if x == 10:
  14.                     last_ten = i

  15.             return total

  16.         s1 = calc_score(player1)
  17.         s2 = calc_score(player2)

  18.         if s1 > s2:
  19.             return 1
  20.         elif s2 > s1:
  21.             return 2
  22.         return 0
复制代码

补充内容 (2026-09-12 09:41 +08:00):
如果想完全避开函数开销的写法
  1. class Solution:
  2. def isWinner(self, player1: list[int], player2: list[int]) -> int:
  3.     s1, s2 = 0, 0
  4.     last1, last2 = -10, -10  # 记录两人的上一次 10 的位置
  5.     for i, (x1, x2) in enumerate(zip(player1, player2)):
  6.         # 处理 player 1
  7.         s1 += 2 * x1 if i - last1 <= 2 else x1
  8.         if x1 == 10:
  9.             last1 = i
  10.         # 处理 player 2
  11.         s2 += 2 * x2 if i - last2 <= 2 else x2
  12.         if x2 == 10:
  13.             last2 = i
  14.     if s1 > s2:
  15.         return 1
  16.     elif s2 > s1:
  17.         return 2
  18.     return 0
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-12 23:22:48 | 只看该作者
全局:
LC. 2656. Maximum Sum With Exactly K Elements
You are given a 0-indexed integer array nums and an integer k. Your task is to perform the following operation exactly k times in order to maximize your score:

Select an element m from nums.
Remove the selected element m from the array.
Add a new element with a value of m + 1 to the array.
Increase your score by m.
Return the maximum score you can achieve after performing the operation exactly k times.



Example 1:

Input: nums = [1,2,3,4,5], k = 3
Output: 18
Explanation: We need to choose exactly 3 elements from nums to maximize the sum.
For the first iteration, we choose 5. Then sum is 5 and nums = [1,2,3,4,6]
For the second iteration, we choose 6. Then sum is 5 + 6 and nums = [1,2,3,4,7]
For the third iteration, we choose 7. Then sum is 5 + 6 + 7 = 18 and nums = [1,2,3,4,8]
So, we will return 18.
It can be proven, that 18 is the maximum answer that we can achieve.
Example 2:

Input: nums = [5,5,5], k = 2
Output: 11
Explanation: We need to choose exactly 2 elements from nums to maximize the sum.
For the first iteration, we choose 5. Then sum is 5 and nums = [5,5,6]
For the second iteration, we choose 6. Then sum is 5 + 6 = 11 and nums = [5,5,7]
So, we will return 11.
It can be proven, that 11 is the maximum answer that we can achieve.


Constraints:

1 <= nums.length <= 100
1 <= nums[i] <= 100
1 <= k <= 100
  1. class Solution:
  2.     def maximizeSum(self, nums: List[int], k: int) -> int:
  3.         maxV = max(nums)
  4.         return k * maxV + k * (k-1) // 2
复制代码
回复

使用道具 举报

🔗
 楼主| Myron2017 2026-9-12 23:47:21 | 只看该作者
全局:
2652. Sum Multiples

Hint
Given a positive integer n, find the sum of all integers in the range [1, n] inclusive that are divisible by 3, 5, or 7.

Return an integer denoting the sum of all numbers in the given range satisfying the constraint.



Example 1:

Input: n = 7
Output: 21
Explanation: Numbers in the range [1, 7] that are divisible by 3, 5, or 7 are 3, 5, 6, 7. The sum of these numbers is 21.
Example 2:

Input: n = 10
Output: 40
Explanation: Numbers in the range [1, 10] that are divisible by 3, 5, or 7 are 3, 5, 6, 7, 9, 10. The sum of these numbers is 40.
Example 3:

Input: n = 9
Output: 30
Explanation: Numbers in the range [1, 9] that are divisible by 3, 5, or 7 are 3, 5, 6, 7, 9. The sum of these numbers is 30.


Constraints:

1 <= n <= 103
  1. class Solution:
  2.     def sumOfMultiples(self, n: int) -> int:

  3.         ans = 0

  4.         for num in range(1, n+1):
  5.             if num % 3 == 0 or num % 5 == 0 or num % 7 == 0:
  6.                 ans += num

  7.         return ans

  8.         
复制代码
改进的解法,数学优化 —— 容斥原理 + 等差数列求和(进阶 $O(1)$ 解法)如果面试官追问:“如果 $n$ 的范围变成 $10^9$,遍历会直接超时(TLE),该怎么优化?”这就需要用到数学方法。上一题(LC 2656)我们用到了等差数列求和,这道题可以进一步结合容斥原理(Inclusion-Exclusion Principle)。数学推导在 $[1, n]$ 范围内,能被 $k$ 整除的数构成一个公差为 $k$ 的等差数列:$$k, 2k, 3k, \dots, m \cdot k \quad (\text{其中 } m = \lfloor n / k \rfloor)$$这些数的和 $S(k)$ 为:$$S(k) = k \times \frac{m(m + 1)}{2}$$要计算能被 3、5 或 7 整除的数之和:先加上能被 3、5、7 整除的数之和:$S(3) + S(5) + S(7)$减去被重复计算的交集(即同时被两者整除的数,相当于最小公倍数):$- S(15) - S(21) - S(35)$加上被多减了一次的三者交集:$+ S(105)$

S= S(3) + S(5) + S(7) - S(15) - S(21) - S(35) + S(105)
  1. class Solution:

  2.     def sumOfMultiples(self, n: int) -> int:
  3.         def sum_divisible(k: int) -> int:
  4.             m = n // k
  5.             return k * m * (m + 1) // 2

  6.         return (
  7.             sum_divisible(3)
  8.             + sum_divisible(5)
  9.             + sum_divisible(7)
  10.             - sum_divisible(15)
  11.             - sum_divisible(21)
  12.             - sum_divisible(35)
  13.             + sum_divisible(105)
  14.         )
复制代码
回复

使用道具 举报

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

本版积分规则

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