题目:
给你一个下标从 0 开始的数组 nums
,数组中的元素都是正整数。请你选出两个下标 i
和 j
(i != j
),且 nums[i]
的数位和 与 nums[j]
的数位和相等。
请你找出所有满足条件的下标 i
和 j
,找出并返回 nums[i] + nums[j]
可以得到的 最大值 。
这道题要搜索满足条件的二元数对,要求这两个数的数位和一样,求最大数对和。
数位和即为表中元素数位相加的和,例:nums[i]=18,则该元素的数位和为1+8=9。
数对和为表中元素i与元素j的值的和,前提是条件是两者的数位和相等,例:nums[i]=18,数位和为9,nums[j]=36,数位和也为9。这两个元素都有共同的数位和,故他们的数对和为18+36=54。
依据贪心的策略,我们要想数对和最大,那么数对中的两个元素都要尽可能的大。
概念引入:贪心法
贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。
可当我们处理一个数位和为 n 的元素时,我们怎么知道当前这个数位和出现过的最大数字是多少呢?
我们可以使用类似两数之和的做法,使用一个哈希表(字典)来存储所有出现过的数位和的最大元素 。
哈希表是根据关键码值(key value)直接访问的数据结构,在python中可以使用字典进行替代,两者同样是使用关键值查找数据。
概念引入:哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
通过将关键字(key)映射到表中一个位置, 可以直接访问记录, 以提高查找的速率,相比较其他的查找结构,哈希表查找的时间复杂度更低。其中用于映射的函数称为哈希函数, 哈希函数有多种,常见的哈希函数包括CRC32,MD5,SHA等。由于哈希表的特殊性质,其在安全加密,数据校验,唯一标识,负载均衡等场景都有着不可替代的作用。
根据题意,将数位和定义为key(键值),遍历列表,当前元素i的数位和若不在字典中,则添加键值对(数位和,当前列表元素)。如果字典中已存在相同数位和,则将数位和相同的两对应元素的值累加,用变量存储本轮的最大数对合。然后依次枚举所有元素,比对本轮最大数对和与历史轮数中最大数对和,保留最大值更新。同时更新字典中的数位和的最大数字,将键值(数位和)对应的最大元素保存在字典中。
这样,每个数位和要么存储了最大数字,在遍历次大数字时得到最大数对和。要么存储了次大数字,在遍历最大数字时得到最大数对和。
算法过程图解:
代码示例(python3):
class Solution:
def maximumSum(self, nums: List[int]) -> int:
# 计算一个数字的数位和
def digit_sum(num: int) -> int:
s = 0
while num:
s += num % 10
num //= 10
return s
map_ = {} # 存储每个数位和的最大数字
res = -1 # 结果,初始为-1,表示没有满足条件的数对
for num in nums:
ds = digit_sum(num) # 计算当前数字的数位和
if ds in map_:
# 如果映射表中存在这个数位和,取映射表中存储的最大值和当前数字相加更新res
res = max(res, num + map_[ds])
map_[ds] = max(num, map_.get(ds, 0)) # 更新映射表中这个数位和对应的最大数字
return res
leetcode题解参考示例:
作者:画图小匠
链接:https://leetcode.cn/problems/max-sum-of-a-pair-with-equal-sum-of-digits/solutions/2531429/javapython3cha-xi-biao-tan-xin-cun-chu-m-bli1/
来源:力扣(LeetCode)
此文章仅做学习笔记记录与知识分享,如有侵权,请联系我删除。