1.题目描述
给你一个下标从 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] <= 104
2.解题思路
1.暴力枚举法:O(n^2)的复杂度枚举每两个数的组合,并且对于每一个数,都使用一个while循环求这个数的最大数位。如果两个数的最大数位相同,那么就相加,直到循环结束,ans中记录的即为满足题意的最大值。这个方法的时间复杂度太高
2.学习的做法:以常量级别的空间复杂度,记录每个最大数位的最大值。就是用一个长为10的数组,下标0-9分别代表了以0-9中任何一个数字为最大数位的最大值。那么只需要一次遍历,对于当前遍历到的数字,求出它的最大数位,然后ans的值肯定为当前数字和它最大数位上的最大值的和,然后如果当前数字大于它最大数为上记录的值,需要更新最大值为当前数字。这样就可以将之前的状态记录在maxVal数组中,从而避免了第二重for循环
3.代码实现
python 常规思路
class Solution:
def getMax(self, num: int) -> int:
cnt = 0
while num:
cnt = max(cnt,num % 10)
num //= 10
return cnt
def maxSum(self, nums: List[int]) -> int:
n = len(nums)
max_val = -1
for i in range(n-1):
for j in range(i+1,n):
if self.getMax(nums[i]) == self.getMax(nums[j]):
max_val = max(max_val,nums[i] + nums[j])
return max_val
Python 一次遍历
class Solution:
def maxSum(self, nums: List[int]) -> int:
max_val = [-inf] * 10
ans = -1
for num in nums:
#求数位最大值
max_d = max(map(int,str(num)))
ans = max(ans,num + max_val[max_d])
#更新max_val数位最大值
max_val[max_d] = max(num,max_val[max_d])
return ans
Java 一次遍历
class Solution {
public int maxSum(int[] nums) {
int ans = -1;
int[] maxVal = new int[10];
Arrays.fill(maxVal, Integer.MIN_VALUE);
for (int v : nums) {
int maxD = 0;
int temp = v;
while (temp > 0) {
maxD = Math.max(maxD,temp % 10);
temp /= 10;
}
ans = Math.max(ans,v + maxVal[maxD]);
maxVal[maxD] = Math.max(maxVal[maxD],v);
}
return ans;
}
}