leetcode
leetcode 2701 ~ 2750
找出可整除性得分最大的整数

找出可整除性得分最大的整数

难度:

标签:

题目描述

You are given two 0-indexed integer arrays nums and divisors.

The divisibility score of divisors[i] is the number of indices j such that nums[j] is divisible by divisors[i].

Return the integer divisors[i] with the maximum divisibility score. If there is more than one integer with the maximum score, return the minimum of them.

 

Example 1:

Input: nums = [4,7,9,3,9], divisors = [5,2,3]
Output: 3
Explanation: The divisibility score for every element in divisors is:
The divisibility score of divisors[0] is 0 since no number in nums is divisible by 5.
The divisibility score of divisors[1] is 1 since nums[0] is divisible by 2.
The divisibility score of divisors[2] is 3 since nums[2], nums[3], and nums[4] are divisible by 3.
Since divisors[2] has the maximum divisibility score, we return it.

Example 2:

Input: nums = [20,14,21,10], divisors = [5,7,5]
Output: 5
Explanation: The divisibility score for every element in divisors is:
The divisibility score of divisors[0] is 2 since nums[0] and nums[3] are divisible by 5.
The divisibility score of divisors[1] is 2 since nums[1] and nums[2] are divisible by 7.
The divisibility score of divisors[2] is 2 since nums[0] and nums[3] are divisible by 5.
Since divisors[0], divisors[1], and divisors[2] all have the maximum divisibility score, we return the minimum of them (i.e., divisors[2]).

Example 3:

Input: nums = [12], divisors = [10,16]
Output: 10
Explanation: The divisibility score for every element in divisors is:
The divisibility score of divisors[0] is 0 since no number in nums is divisible by 10.
The divisibility score of divisors[1] is 0 since no number in nums is divisible by 16.
Since divisors[0] and divisors[1] both have the maximum divisibility score, we return the minimum of them (i.e., divisors[0]).

 

Constraints:

  • 1 <= nums.length, divisors.length <= 1000
  • 1 <= nums[i], divisors[i] <= 109

代码结果

运行时间: 1574 ms, 内存: 16.1 MB


/*
思路:
1. 使用 Java Stream API 来计算每个除数的可整除性得分。
2. 创建一个 Map 来存储每个除数及其对应的得分。
3. 使用 Stream 的 max 方法找到得分最大且数值最小的除数。
4. 返回该除数。
*/
import java.util.*;
import java.util.stream.*;

public class Solution {
    public int maxDivScore(int[] nums, int[] divisors) {
        Map<Integer, Long> scores = Arrays.stream(divisors)
                .boxed()
                .collect(Collectors.toMap(d -> d, d -> Arrays.stream(nums).filter(n -> n % d == 0).count()));

        return scores.entrySet().stream()
                .max(Comparator.comparing((Map.Entry<Integer, Long> entry) -> entry.getValue())
                        .thenComparing(Map.Entry::getKey, Comparator.reverseOrder()))
                .get()
                .getKey();
    }
}

解释

方法:

该题解采用了排序和暴力搜索的方法。首先对divisors数组进行升序排序,以便在遇到多个得分最大的整数时返回最小的一个。然后,对nums数组进行降序排序,这样在遍历nums时,一旦遇到小于当前divisor的元素,就可以提前终止内层循环,从而减少不必要的计算。接着,遍历每个divisor,计算其可整除性得分,并更新最大得分及对应的divisor。

时间复杂度:

O(m log m + n log n + mn)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在计算可整除性得分时要先对nums数组进行降序排序?这种排序方式如何帮助提前终止内层循环?
对nums数组进行降序排序的目的是在内层循环中尽早发现不符合条件的情况从而提前终止循环,节省计算资源。在降序排序后,nums数组中的元素从大到小排列。当遍历这些元素时,一旦发现一个元素n小于当前的divisor,由于所有后续的元素都会更小(因为数组已经排序),它们也必然小于divisor,因此不可能被divisor整除。这时可以立即终止内层循环,避免了对后续更小的无效数字的无效检查。
🦆
在遍历divisors数组时,如果当前divisor的得分已经超过了某个阈值(例如所有nums元素的数量),是否有必要继续计算后续divisors的得分?
如果在某一点上,divisor的得分已经等于nums数组的长度,这意味着所有nums中的元素都能被这个divisor整除。这已经是可能的最大得分,因此没有继续计算其他divisors得分的必要。这是因为得分不可能超过nums数组的长度,继续计算只会消耗额外的计算资源而不会改变结果。然而,如果得分没有达到这个最大可能值,那么仍需要继续遍历其他divisors,因为可能有更高得分的divisor存在。
🦆
对于divisors的排序,为什么选择升序排序?升序排序除了在得分相同时返回最小的divisor外,还有其他作用吗?
主要作用是确保在找到多个具有相同最高得分的divisors时能返回最小的那个。升序排序确保了在更新得分记录时,较小的divisor会首先被考虑,从而在得分相同时自然选择最小的divisor。此外,从理论上讲,排序本身没有直接影响算法性能,因为不论如何排序,算法都需要遍历所有divisors来计算得分。因此,选择升序排序主要是为了满足题目要求返回最小的divisor。

相关问题