给定n个元素的数组,只允许执行2种操作以使数组的所有元素相等。
您的任务是尽量减少为使阵列的所有元素相等所执行的上述操作的总数。
实施例
array = [3,6,7]最小操作为2为6,7可以除以2得到3。
我甚至想不到蛮力解决方案。
约束 1< = n< = 100000和 1< = ai< = 100000 其中ai是数组的第i个元素。
答案 0 :(得分:4)
0
和1
的字符串。例如:3, 6, 7
分别表示为11, 110, 111
。
2
相当于删除最右侧的0
或1
,乘以2
相当于从右侧添加0
对于由0
和1
组成的字符串,让我们将其“head”定义为子字符串,该字符串是字符串的左边几个术语,以1
结尾。
例如:1100101
有头1
,11
,11001
,1100101
。
0
。一个例子:
假设您有以下字符串:
10101001
,101011
,10111
,1010001
10101001
和101011
的最长公共头,即10101
; 10101
和10111
的最长公共头,即101
; 101
和1010001
的最长公共头,即101
。然后您确定所有数字都应该成为101 00...
形式的数字。
要确定0
之后要添加的101
个,请在每个字符串中找到0
后面的连续101
个数:
10101001
:1
101011
:1
10111
:0
1010001
:3
仍然需要找到一个最小化k
的整数|k - 1| + |k - 1| + |k - 0| + |k - 3|
。我们在这里找到k = 1
。所以每个号码最后应该是1010
。
答案 1 :(得分:2)
正如另一个答案所解释的那样,回溯是没有必要的。为了它的乐趣,该方法的一点实现。 (参见底部在线运行的链接):
首先,我们需要一个确定数字中二进制数字位数的函数:
def getLength(i: Int): Int = {
@annotation.tailrec
def rec(i: Int, result: Int): Int =
if(i > 0)
rec(i >> 1, result + 1)
else
result
rec(i, 0)
}
然后我们需要一个函数来确定两个等长的数字
的公共前缀 @annotation.tailrec
def getPrefix(i: Int, j: Int): Int =
if(i == j) i
else getPrefix(i >> 1, j >> 1)
以及任意数字列表:
def getPrefix(is: List[Int]): Int = is.reduce((x,y) => {
val shift = Math.abs(getLength(x) - getLength(y))
val x2 = Math.max(x,y)
val y2 = Math.min(x,y)
getPrefix((x2 >> shift), y2)
})
然后我们需要后缀的长度而不计算后缀的出租零:
def getSuffixLength(i: Int, prefix: Int) = {
val suffix = i ^ (prefix << (getLength(i) - getLength(prefix)))
getLength(suffix)
}
现在我们可以计算将操作i与前缀同步的操作数量&#34; zeros&#34;附加零。
def getOperations(i: Int, prefix: Int, zeros: Int): Int = {
val length = getLength(i) - getLength(prefix)
val suffixLength = getSuffixLength(i, prefix)
suffixLength + Math.abs(zeros - length + suffixLength)
}
现在我们可以找到最少数量的操作并将其与我们将要同步的值一起返回:
def getMinOperations(is: List[Int]) = {
val prefix = getPrefix(is)
val maxZeros = getLength(is.max) - getLength(prefix)
(0 to maxZeros).map{zeros => (is.map{getOperations(_, prefix, zeros)}.sum, prefix << zeros)}.minBy(_._1)
}
您可以在以下位置尝试此解决方案:
可以改进找到正确数量的零的最后一步,因为只有没有前导零的后缀的长度很重要,而不是它看起来像什么。因此,我们可以通过计算有多少操作来计算我们需要的操作数量:
def getSuffixLength(i: Int, prefix: Int) = {
val suffix = i ^ (prefix << (getLength(i) - getLength(prefix)))
getLength(suffix)
}
def getMinOperations(is: List[Int]) = {
val prefix = getPrefix(is)
val maxZeros = getLength(is.max) - getLength(prefix)
val baseCosts = is.map(getSuffixLength(_,prefix)).sum
val suffixLengths: List[(Int, Int)] = is.foldLeft(Map[Int, Int]()){
case (m,i) => {
val x = getSuffixLength(i,prefix) - getLength(i) + getLength(prefix)
m.updated(x, 1 + m.getOrElse(x, 0))
}
}.toList
val (minOp, minSol) = (0 to maxZeros).map{zeros => (suffixLengths.map{
case (x, count) => count * Math.abs(zeros + x)
}.sum, prefix << zeros)}.minBy(_._1)
(minOp + baseCosts, minSol)
}
所有腋窝操作仅以最大数量的大小取对数时间。我们必须通过孔列表来收集后缀长度。然后我们必须猜测最多对数的零的数量,其中最大数量为零。
应该具有复杂性O(|list|*ld(maxNum) + (ld(maxNum))^2)
因此,对于你的界限,这在输入大小上基本上是线性的。
此版本可在此处找到: