leetcode
leetcode 2251 ~ 2300
统计桌面上的不同数字

统计桌面上的不同数字

难度:

标签:

题目描述

You are given a positive integer n, that is initially placed on a board. Every day, for 109 days, you perform the following procedure:

  • For each number x present on the board, find all numbers 1 <= i <= n such that x % i == 1.
  • Then, place those numbers on the board.

Return the number of distinct integers present on the board after 109 days have elapsed.

Note:

  • Once a number is placed on the board, it will remain on it until the end.
  • % stands for the modulo operation. For example, 14 % 3 is 2.

 

Example 1:

Input: n = 5
Output: 4
Explanation: Initially, 5 is present on the board. 
The next day, 2 and 4 will be added since 5 % 2 == 1 and 5 % 4 == 1. 
After that day, 3 will be added to the board because 4 % 3 == 1. 
At the end of a billion days, the distinct numbers on the board will be 2, 3, 4, and 5. 

Example 2:

Input: n = 3
Output: 2
Explanation: 
Since 3 % 2 == 1, 2 will be added to the board. 
After a billion days, the only two distinct numbers on the board are 2 and 3. 

 

Constraints:

  • 1 <= n <= 100

代码结果

运行时间: 13 ms, 内存: 16.0 MB


/*
 * 题目思路:
 * 与Java普通解法类似,但是利用Java Stream流式编程来实现。
 * 初始时数字n在桌面上,之后每一天都会在桌面上寻找满足条件的数字。
 * 这些满足条件的数字会一直保留在桌面上直到结束。
 * 因此,我们只需要计算出这些满足条件的数字数量即可。
 */
import java.util.stream.IntStream;

public class Solution {
    public int distinctIntegers(int n) {
        // 初始值为1,因为n本身就在桌面上
        return (int) IntStream.range(2, n) // 生成范围为2到n-1的数字流
                .filter(i -> n % i == 1) // 过滤出n % i == 1的数字
                .count() + 1; // 计数,并加上n本身的1个计数
    }
}

解释

方法:

此题解使用一个集合 `board` 来存储每一天结束时桌面上的所有数字。初始时,集合中只包含数字 `n`。每天对当前集合中的每个数字 `x` 进行遍历,对于每个 `x`,再次遍历从 `1` 到 `x-1` 的所有整数 `i`,检查 `x % i == 1` 是否成立。如果条件满足,则将 `i` 添加到一个新的临时集合 `new_board` 中。如果在某一天结束时 `new_board` 和 `board` 相同,意味着没有新的数字被添加到集合中,因此可以停止迭代,返回集合中不同整数的数目。这反映出了算法的收敛性,即达到了一个固定点,新的数字不再被生成。

时间复杂度:

O(n^2)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么选择使用集合(set)数据结构来存储桌面上的数字,而不是列表(list)或其他容器?
选择使用集合(set)的主要原因是集合在查找和插入操作中提供了平均时间复杂度为 O(1) 的性能,这使得每次添加和检查元素是否存在时都非常高效。对比之下,如果使用列表(list),则每次查找元素是否存在的操作的时间复杂度为 O(n),这会显著增加算法的总运行时间。此外,集合自动处理重复元素,确保存储的每个数字都是唯一的,无需额外的逻辑来处理重复性。
🦆
在算法中,为何需要检查新集合`new_board`和旧集合`board`是否相同来决定是否继续迭代,这种方法的时间复杂度是多少?
检查新集合`new_board`与旧集合`board`是否相同是为了确定算法是否达到了一个稳定状态,即后续不会再有新的元素被添加到集合中。这种检查是必要的,因为一旦集合中的元素不再发生变化,继续迭代将不会产生新的结果,只会增加不必要的计算。对于时间复杂度,集合比较操作通常是 O(n),其中 n 是集合中元素的数量。因此,此操作的复杂度与集合大小直接相关。
🦆
遍历从1到x-1的整数时,算法是否考虑了任何优化措施以降低时间复杂度,例如跳过某些不必要的检查?
根据题解代码,算法没有明显采用特别的优化措施来减少遍历的次数或跳过某些检查。它简单地遍历从1到x-1的每个数字,检查每个数字i是否满足x % i == 1。这种方法虽然简单,但在x较大时可能效率不高。一种可能的优化方法是在确定某些数学属性(例如因子的特征)后减少检查范围,但在当前算法实现中并未体现这种优化。

相关问题