问题描述
小U有一个数组,她可以通过选择一个元素并将其除以2(向下取整)的操作来改变数组。小U想知道,最少需要多少次这样的操作才能使得所有数组元素相等。
测试样例
样例1:
输入:
n = 4 ,a = [1, 2, 1, 3]
输出:2
样例2:
输入:
n = 1 ,a = [114514]
输出:0
样例3:
输入:
n = 5 ,a = [16, 8, 4, 2, 1]
输出:10
解题思路
这道题目的解题思路其实很简单明了,题目要求经过操作后使得所有数组元素相等,那么,我们就需要找到一个值使得数组中的每个元素等于或经过至少一次的除以2(向下取整)的操作后等于这个值,又因为需要最少的操作次数,那么这个值就需要为满足上面条件中的最大值(因为值越大,其他元素变为该值所需要的操作次数就越少)。这个值确定以后,我们只需要统计数组中每个元素变为该值所需要操作的次数并求和即可得出最终的答案。下面结合代码给大家解释一下具体的实现步骤。
代码展示
def solution(n: int, a: list) -> int:
if n==1:
return 0
else:
num=0
if 1 in a or 0 in a:
for i in range(n):
while a[i]>min(a):
a[i]//=2
num+=1
return num
else:
total = []
for i in range(n):
temp = [a[i]]
while a[i]>1:
a[i]//=2
temp.append(a[i])
total.append(temp)
total.sort(key=lambda x:len(x))
same_num = 1
for i in total[0]:
if all(i in lst for lst in total[1:]):
same_num=i
break
for lst in total:
num +=lst.index(same_num)
return num
代码说明
第一步,判断数组长度是否为1,长度为1时,直接返回0,因为数组中就一个元素,所有元素相等,不需要进行操作。
第二步,先定义一个变量num用来记录所需要的操作次数,然后紧接着是一个if-else结构,这个结构是用来判断数组中是否含有元素1或0。为什么要进行这样一个判断呢(当然,这里不单独进行判断也是可以的,只不过我认为含有1或0时没必要进行后面那些步骤,所以单独拎出来做了一下判断)?因为,当数组中含有1或0时,我们所需要找的那个值不是1就是0(目标值是不可能大于数组中的任何一个元素的,因为操作只能使元素变小,不能使元素变大。此外,所有大于1的元素都能经过操作变为1或0)也就是min(a)。然后我们只需要记录每个元素变为该值所需要的次数即可得出答案。
第三步,处理其他情况。当数组中不含1和0时,我们就需要动手找出目标值。这就需要我们对每个元素不断的进行操作并记录该元素经过操作后的一系列结果,然后,我们就可以根据每个元素的结果(即每个元素经过操作可以变为的值)来确定我们的目标值。首先定义一个total列表用来存放后续的各个子列表,然后对各个元素不断的进行操作并将相应结果保存在列表中,最后将这个子列表添加到total中。然后我们,对这个Total中的所有元素求交集并找出其中的最大值即为目标值,最后根据该目标值在各个子列表中的位置即可确定各个元素所需要进行的操作次数,求和即为最终的答案