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 <= 100
1 <= 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 List
List
用于类型注解,增强代码的可读性和可维护性。
-
定义
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 ans
ans
初始化为-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_
,不随输入规模变化。
- 我们使用了一个长度固定为
总结
本题要求我们在数组中找到一对数,使得这对数中每个数的数位上最大的数字相等,并且这对数的和尽可能大。通过以下步骤,我们能够高效地解决问题:
- 确定每个数的数位上最大的数字。
- 使用一个固定大小的数组记录每个最大数字对应的最大数。
- 在遍历过程中更新记录并计算可能的最大和。
这种方法不仅简单直观,而且在时间和空间复杂度上都非常高效,适用于处理题目中给定的约束条件。如果你有任何疑问或更优化的解法,欢迎在评论区交流分享!