您有一系列d[0] , d[1], d[2] , d[3] ,..,d[n]
。在每次移动中,您可以将任何d [i]增加1或2或5 i:0增加到n。将序列转换为[1,2,3,..,n] if it's possible else return -1. 1<=n<=1000
的排列所需的最小移动次数
我的方法是在升序数组中对给定数组进行排序,而不是通过添加1或2或5对其进行计数。但在许多情况下它失败了。Some of my classmates did this in exam using this method but they read question wrong so read question carefully .
e.g。 [1,1,3,2,1]比答案是4因为我们可以分别加0,1,2,2,2得到[1,2,5,4,3]所以答案是4。
[1,2,3,4,1] =&gt; [1,1,2,3,4]我们将使用排序方法[0,1,1,1,1]获得4,但答案是2,因为我们可以在[1]中添加[2 + 2]来获得[1,2,1,1] ,3,4,5]。
同样[1,2,3,1] =&gt; [1,1,2,3]到[1,2,3,4]需要3次转换但是答案是2,因为添加[1 + 2]到1我们可以得到[1,2,3,4]。
另一种方法可以用作i don't have any proof for correctness
。
Algorithm
input "n" is number of element , array "a" which contains input element
initialize cnt = 0 ;
initialize boolarray[n] ={0};
1. for i=0...n boolarray[a[i]]=1;
2. put all element in sorted order whose boolarray[a[i]]=0 for i=0...n
3. Now make boolarray[a[i]]=1; for i=0..n and count
how many additions are required .
4. return count ;
根据我的说法,这个问题将导致0或更多,因为除了这种情况,当任何d [i] i = 0..n大于输入数时,可以使用1,2和5生成任何数字。
How to solve this correctly ?
欢迎任何答案和建议。
答案 0 :(得分:1)
您的问题可以转换为weighted bipartite matching问题: -
- 图的第一部分p1是当前数组编号作为节点。
- 图的第二部分p2是数字1到n。
- 如果我们可以在它添加1,2,5以在p2中创建节点,则在p1到节点p2的节点之间存在边缘。
- 加权二分匹配可以使用匈牙利算法
来解决 醇>
修改: -
如果您正在评估最小移动次数,则可以使用unweighted bipartite matching。您可以使用 hopcroft-karp算法,在您的情况下在O(n^1.5)
中运行,作为图表中的边数E = O(n)
。
答案 1 :(得分:0)
创建一个数组count
,其中包含我们在基础数组中有特定数字的频率
input 1 1 3 2 1
count 3 1 1 0 0
现在遍历此数组并计算步骤
sum = 0
for i: 1..n
while count[i] > 1 // as long as we have spare numbers
missing = -1 // find the biggest empty spot which is bigger than the number at i
for x: n..i+1 // look for the biggest missing
if count[x] > 0 continue // this one is not missing
missing = x
break;
if missing == -1 return -1 // no empty spot found
sum += calcCost(i, missing)
count[i]--
count[missing]++
return sum
calcCost必须贪心