我在最近的一次采访中遇到了这个问题:
给出一个整数数组和一个整数k。您可以对数组中任意数量的元素执行任意次数的操作(可能为零):
如果数字可被k整除,则将其除以k(如果数字可被k整除,则不允许将其乘以k)
如果数字不能被k整除,则将其乘以k
您需要以以下方式更新此数组:数组中最大数量和最小数量之间的差异最小,并为此找到最小数量的操作。
例如令a [5] = {82,79,38,49,9}并且k = 5,我们对最后一个元素应用第二次运算。现在,a [5] = {82,79,38,49,9 * 5},此更新后的数组给出了最小数和最大数之间的最小差,即max-min = 82-38 = 44
我正在考虑应用固定一个数字的递归解决方案,并尝试将所有数字保持与固定数字接近。
但是需要更好的方法来有效解决此问题。 预先感谢。
答案 0 :(得分:4)
这在O(NlogN)
中可行。对于每个元素,我们可以写出它可以转换成的每个元素。因此,让每个元素转换成可以变成的候选元素列表。现在问题变成了smallest range covering elements from k lists,可以在O(NlogN)
中完成。
解决最小范围问题的一种非常简单的方法:
在合并列表上运行一个滑动窗口,该列表具有每个子列表中的一个元素
采用候选范围
以下是我对最小范围问题的解决方案。您只需要一些样板代码即可将整数列表转换为列表列表。
from collections import deque, Counter
class Solution:
def smallestRange(self, nums: List[List[int]]) -> List[int]:
new = []
# merge each list and keep track of original list
for i in range(len(nums)):
for j in nums[i]:
new.append((j, i))
# sort so each sliding window represents a range
new.sort()
d = deque()
c = Counter()
res = [-float('inf'), float('inf')]
# iterate over sliding windows that contain each list
for i in new:
d.append(i)
c[i[1]] += 1
while len(c) == len(nums):
res = min(res, [d[0][0], d[-1][0]], key = lambda x: x[1] - x[0])
a, b = d.popleft()
c[b] -= 1
if not c[b]: del c[b]
return res