LeetCode 第2815题:数组中的最大数对和
在本篇博客中,我们将深入探讨 LeetCode 第2815题:数组中的最大数对和。我们将详细解析题目描述,理解约束条件,并逐步讲解一个高效的 Python 解法,帮助你有效解决这一问题。
题目描述
给你一个下标从 0 开始的整数数组 nums。请你从 nums 中找出和 最大 的一对数,且这两个数数位上最大的数字相等。
返回 最大和 ,如果不存在满足题意的数字对,返回 -1。
示例
示例 1:
输入:nums = [51,71,17,24,42]
输出:88
解释:
i = 1 和 j = 2,nums[i] 和 nums[j] 数位上最大的数字相等,且这一对的总和 71 + 17 = 88。
i = 3 和 j = 4,nums[i] 和 nums[j] 数位上最大的数字相等,且这一对的总和 24 + 42 = 66。
可以证明不存在其他数对满足数位上最大的数字相等,所以答案是 88。
示例 2:
输入:nums = [1,2,3,4]
输出:-1
解释:不存在数对满足数位上最大的数字相等。
约束条件
2 <= nums.length <= 1001 <= nums[i] <= 10^4
解题思路
这道题目要求我们在数组 nums 中找到一对数,使得这对数中每个数的数位上最大的数字相等,并且这对数的和尽可能大。如果不存在这样的数对,则返回 -1。
为了高效地解决这个问题,我们可以按照以下步骤进行:
-
确定每个数的数位上最大的数字 :
对于数组中的每个数,我们需要找出其数位上的最大数字。例如,数
71的数位上最大的数字是7。 -
记录每个最大数字对应的最大数 :
我们可以使用一个长度为
10的数组max_来记录每个可能的最大数字(0-9)对应的最大数。初始化时,将所有位置设为负无穷大,以便后续比较。 -
遍历数组,更新
max_并计算可能的最大和 :对于数组中的每个数
x,我们首先找到它数位上的最大数字a。然后,我们检查当前a对应的max_[a]是否已经存在一个数,如果存在,我们可以计算max_[a] + x并更新答案。接着,我们更新max_[a]为当前数x的最大值。 -
返回结果 :
最后,如果找到符合条件的数对,则返回最大的和;否则,返回
-1。
关键点
- 数位上最大的数字:对于每个数,我们需要找出其数位上的最大数字。这可以通过将数转换为字符串后逐位比较得到。
- 记录最大值 :使用一个数组
max_来记录每个可能的最大数字对应的最大数,可以在遍历过程中快速查找和更新。 - 时间复杂度:由于遍历数组一次,每个操作都是常数时间,因此整体时间复杂度为 O(n),其中 n 是数组的长度。
代码实现
以下是基于上述思路的 Python 实现:
python
from typing import List
class Solution:
def maxSum(self, nums: List[int]) -> int:
ans = -1
max_ = [float('-inf')] * 10 # 初始化最大值数组,索引代表最大数字(0-9)
for x in nums:
# 找出数x数位上的最大数字a
a = max(int(digit) for digit in str(x))
# 如果当前a已经有记录的最大数,计算当前和并更新答案
if max_[a] != float('-inf'):
ans = max(ans, max_[a] + x)
# 更新max_[a]为当前数x和之前记录的最大数中的较大者
max_[a] = max(max_[a], x)
return ans
代码解析
-
导入必要的模块:
pythonfrom typing import ListList用于类型注解,增强代码的可读性和可维护性。
-
定义
Solution类和maxSum方法:pythonclass Solution: def maxSum(self, nums: List[int]) -> int: ans = -1 max_ = [float('-inf')] * 10 for x in nums: a = max(int(digit) for digit in str(x)) if max_[a] != float('-inf'): ans = max(ans, max_[a] + x) max_[a] = max(max_[a], x) return ansans初始化为-1,用于记录最终的最大和。max_是一个长度为10的数组,用于记录每个可能的最大数字(0-9)对应的最大数,初始值设为负无穷大。- 遍历数组
nums中的每个数x:- 将数
x转换为字符串,并逐位比较找出其中最大的数字a。 - 如果
max_[a]已经有记录(即不是负无穷大),则计算max_[a] + x并更新ans。 - 更新
max_[a]为当前数x和之前记录的max_[a]中的较大者。
- 将数
示例讲解
示例 1:
输入:nums = [51,71,17,24,42], k = 10
输出:88
-
步骤:
x = 51,最大数字a = 5。max_[5] = max(-inf, 51) = 51。x = 71,最大数字a = 7。max_[7] = max(-inf, 71) = 71。x = 17,最大数字a = 7。max_[7]已有71,计算71 + 17 = 88,更新ans = 88。然后更新max_[7] = max(71, 17) = 71。x = 24,最大数字a = 4。max_[4] = max(-inf, 24) = 24。x = 42,最大数字a = 4。max_[4]已有24,计算24 + 42 = 66,ans保持为88。然后更新max_[4] = max(24, 42) = 42。
-
结果 :最终
ans = 88。
示例 2:
输入:nums = [1,2,3,4], k = 1
输出:-1
-
步骤:
x = 1,最大数字a = 1。max_[1] = max(-inf, 1) = 1。x = 2,最大数字a = 2。max_[2] = max(-inf, 2) = 2。x = 3,最大数字a = 3。max_[3] = max(-inf, 3) = 3。x = 4,最大数字a = 4。max_[4] = max(-inf, 4) = 4。
-
结果 :没有找到任何数对满足数位上最大的数字相等,因此返回
-1。
复杂度分析
-
时间复杂度 :O(n),其中
n是数组nums的长度。- 我们只需要遍历数组一次,每次操作都是常数时间。
-
空间复杂度:O(1)。
- 我们使用了一个长度固定为
10的数组max_,不随输入规模变化。
- 我们使用了一个长度固定为
总结
本题要求我们在数组中找到一对数,使得这对数中每个数的数位上最大的数字相等,并且这对数的和尽可能大。通过以下步骤,我们能够高效地解决问题:
- 确定每个数的数位上最大的数字。
- 使用一个固定大小的数组记录每个最大数字对应的最大数。
- 在遍历过程中更新记录并计算可能的最大和。
这种方法不仅简单直观,而且在时间和空间复杂度上都非常高效,适用于处理题目中给定的约束条件。如果你有任何疑问或更优化的解法,欢迎在评论区交流分享!