6120. 数组能形成多少数对
链接: 数组能形成多少数对
描述:
给你一个下标从 0 开始的整数数组 nums 。在一步操作中,你可以执行以下步骤:
- 从 nums 选出 两个 相等的 整数
- 从 nums 中移除这两个整数,形成一个 数对
请你在 nums 上多次执行此操作直到无法继续执行。
返回一个下标从0
开始、长度为2
的整数数组answer
作为答案,其中answer[0]
是形成的数对数目,answer[1]
是对nums
尽可能执行上述操作后剩下的整数数目。
个人思路:
用一个Counter遍历数组,每次添加判断一下当前数字的数量是否=2,如果是就更新answer同时把Counter[num]置0
class Solution(object):
def numberOfPairs(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
ans = [0, 0]
ans[1] = len(nums)
m = collections.Counter()
for num in nums:
m[num] += 1
if m[num] == 2:
ans[0] += 1
ans[1] -= 2
m[num] = 0
return ans
Better
待更新
6164. 数位和相等数对的最大和
链接: 数位和相等数对的最大和
描述:
给你一个下标从 0 开始的数组
nums
,数组中的元素都是 正 整数。请你选出两个下标i
和j
(i != j
),且nums[i]
的数位和 与nums[j]
的数位和相等。
请你找出所有满足条件的下标i
和j
,找出并返回nums[i] + nums[j]
可以得到的 最大值 。
个人思路:
因为是最大和,我想先降序然后再遍历构建数位和相等的哈希表(其中key = 数位和
;value = list[]
)这样能保证哈希表里的数组也都是降序,这样在找最大和的时候只需要判断每个数组的头两个元素和。
class Solution:
def maximumSum(self, nums: List[int]) -> int:
# 计算数位和函数:从个位开始依次取
def calculate_sum(num):
_sum = 0
while num:
_sum += (num % 10)
num = num // 10
return _sum
# 先把nums降序
nums.sort(reverse=True)
# 构建数位和相等的哈希表
hashmap = collections.defaultdict(list)
for num in nums:
key = calculate_sum(num)
hashmap[key].append(num)
# 遍历哈希表的key,对数目大于2的key进行求和,维护一个max
ans = -1
for key in hashmap:
if len(hashmap[key]) >= 2:
ans = max(ans, hashmap[key][0] + hashmap[key][1])
return ans
Better:
待更新
6121. 裁剪数字后查询第 K 小的数字
链接: 裁剪数字后查询第 K 小的数字
描述:
给你一个下标从 0 开始的字符串数组
nums
,其中每个字符串 长度相等 且只包含数字。再给你一个下标从 0 开始的二维整数数组
queries
,其中queries[i] = [ki, trimi]
。对于每个queries[i]
,你需要:
- 将
nums
中每个数字 裁剪 到剩下 最右边trimi
个数位。- 在裁剪过后的数字中,找到
nums
中第ki
小数字对应的 下标。如果两个裁剪后数字一样大,那么下标 更小 的数字视为更小的数字。- 将
nums
中每个数字恢复到原本字符串。请你返回一个长度与
queries
相等的数组answer
,其中answer[i]
是第i
次查询的结果。提示:
- 裁剪到剩下 x 个数位的意思是不断删除最左边的数位,直到剩下 x 个数位。
- nums 中的字符串可能会有前导 0 。
个人思路:
- 先用
crop_str(array, n)
裁剪,输出裁剪后的数组sub_arr[]
,其中sub_arr
里的元素是(num, index)
,裁剪后的数字和它的下标; - 对
sub_arr
进行sort()
排序 - 输出
sub[k-1]
对应的下标
刚开始不知道把下标也作为数组的元素之一,导致后面甚至使用到了堆排序来pop前k个,不过这样没办法保证遇到相同元素时输出的下标是正确的。
class Solution(object):
def smallestTrimmedNumbers(self, nums, queries):
"""
:type nums: List[str]
:type queries: List[List[int]]
:rtype: List[int]
"""
# 裁剪函数
def crop_str(array, n):
sub_arr = []
for i, ch in enumerate(array):
sub_arr.append((int(ch[-n:]), i))
return sub_arr
res = []
for query in queries:
arr = crop_str(nums, query[1])
arr.sort() # 排序
res.append(arr[query[0]-1][1]) # 输出第k小的元素下标
return res
Better:
评论区扣到的,思路差不多(大概)不过处理的更好更快更精简。
还看到有用基数排序的,我还没学到代码实现所以先不放了。
class Solution(object):
def smallestTrimmedNumbers(self, nums, queries):
"""
:type nums: List[str]
:type queries: List[List[int]]
:rtype: List[int]
"""
ans=[]
for k,trim in queries:
tmp=[(num[-trim:],i) for i,num in enumerate(nums)]
tmp.sort()
ans.append(tmp[k-1][1])
return ans
6122. 使数组可以被整除的最少删除次数
题目链接
描述:
给你两个正整数数组
nums
和numsDivide
。你可以从nums
中删除任意数目的元素。
请你返回使nums
中 最小 元素可以整除numsDivide
中所有元素的 最少 删除次数。如果无法得到这样的元素,返回-1
。
如果y % x == 0
,那么我们说整数x
整除y
。
示例 1:
输入:nums = [2,3,2,4,3], numsDivide = [9,6,9,3,15]
输出:2
解释:
[2,3,2,4,3] 中最小元素是 2 ,它无法整除 numsDivide 中所有元素。
我们从 nums 中删除 2 个大小为 2 的元素,得到 nums = [3,4,3] 。
[3,4,3] 中最小元素为 3 ,它可以整除 numsDivide 中所有元素。
可以证明 2 是最少删除次数。
思路:
求最大公因数,先排序,从小到大找到第一个能整除g的元素x,所有小于x的元素都需要删除。
class Solution:
def minOperations(self, nums: List[int], numsDivide: List[int]) -> int:
g = reduce(gcd, numsDivide)
nums.sort()
return next((i for i, x in enumerate(nums) if g % x == 0), -1)
这个是评论区扣的,当时时间问题没有写到这一题
回头再来细看。