打印所需的最小移动次数,以便所有元素都等于最小元素

问题描述

只需一步,我们就可以使它等于第二个最大元素,并且必须使所有元素等于最小元素。 下面给出了我的代码,它工作正常,但我想降低它的时间复杂度。

def No_Books(arr,n):
    arr = sorted(arr)
    steps = 0
    while arr[0]!= arr[arr.index(max(arr))]:
        max1 = max(arr)
        count = arr.count(max1)
        scnd_max = arr.index(max1)-1
        arr[scnd_max+count] = arr[scnd_max]
        steps += 1
    return steps

n = int(input())
arr = [int(x) for x in input().split()]
print(No_Books(arr,n))

输出

5
4 5 5 2 4

6

这里需要的最小移动是 6

解决方法

我是这样解释这个问题的:

对于数组中的每个元素,您只能执行一项操作,该操作是将索引的值替换为数组的当前第二大元素。

需要多少次操作才能使整个数组的值等于初始最小值?

使用示例输入 4 5 5 2 4 需要经过以下步骤:

Array     - step - comments
4 5 5 2 4 - 0 - start
4 4 5 2 4 - 1 - replace the first 5 with 4 (the second-largest value in the array)
4 4 4 2 4 - 2 - replace the second 5 with 4
2 4 4 2 4 - 3 - replace the first 4 with 2
2 2 4 2 4 - 4
2 2 2 2 4 - 5
2 2 2 2 2 - 6
It took 6 steps,so the result is 6.

如果这是正确的,那么我可以将您的二次解(O(n^2),其中 n 是数组的大小)更改为拟线性解(O(n + mlogm),其中 n 是数组的大小)数组,m 是数组中唯一值的个数),如下所示。

该方法是注意对于每个小于自身的唯一值,每个值都需要下降到下一个最大值。因此,如果我们能够跟踪每个唯一值的计数,我们就可以确定步数,而无需实际进行任何数组更新。

在伪代码中:

function determineSteps(array):
  define map from integer to integer,defaulting to 0

  for each value in array: // Linear in N
    map(value)++

  sort map by key,descending // M log M

  // largerCount is the number of elements larger than the current second-largest value
  define largerCount,assign 0 to largerCount
  // stepCount is the number of steps required
  define stepCount,assign 0 to stepCount

  for each key in map except the last: // Linear in M
    largerCount = largerCount + map(key)
    stepCount = stepCount + largerCount

  return stepCount

在您的示例输入中:

4 5 5 2 4
Create map { 4: 2,5: 2,2: 1 }
Sort map by key,descending: { 5: 2,4: 2,2: 1 }
stepCount = 0
largerCount = 0
Examine key = 5,map(key) = 2
largerCount = 0 + 2 = 2 
stepCount = 0 + 2 = 2
Examine key = 4,map(key) = 2
largerCount = 2 + 2 = 4
stepCount = 2 + 4 = 6
return 6