Algorithm 最低掉期金额
假设我们得到了1和0的序列(长度Algorithm 最低掉期金额,algorithm,Algorithm,假设我们得到了1和0的序列(长度n),例如10100100。我们想重新排列它们,所以1跟随每个0,而0跟随每个1——但最后可能会有一些0或1剩下,所以我们的序列将变成10101000。假设有k数量的1和n-k数量的0,所以我们需要有min(n,n-k)组10(或01)然后剩下的 我们可以做一个操作——交换两个选定的元素。我们需要计算将序列重新排列为给定顺序的最小交换量-例如,我们只需要一次交换(在索引4和5之间,从0索引),就可以正确地重新排列。对于0101011111或10101000000我
n
),例如10100100
。我们想重新排列它们,所以1
跟随每个0
,而0
跟随每个1
——但最后可能会有一些0
或1
剩下,所以我们的序列将变成10101000
。假设有k
数量的1
和n-k
数量的0
,所以我们需要有min(n,n-k)
组10
(或01
)然后剩下的
我们可以做一个操作——交换两个选定的元素。我们需要计算将序列重新排列为给定顺序的最小交换量-例如,我们只需要一次交换(在索引4
和5
之间,从0
索引),就可以正确地重新排列。对于0101011111
或10101000000
我们需要0
交换
你知道怎么计算吗?实际上,任何复杂性都会受到影响-我不知道如何做到这一点。根据您的示例,我假设您的多余字符必须出现在字符串的右侧。这意味着前面的字符必须交替。这只为最终字符串提供了两种可能的解决方案。在你给出的情况下,这些将是
10101000
01010100
整个算法很简单:生成这两个序列(k
0与k
1交替),并附加n-k
extra。将每一个字符与原始字符进行比较,看看哪一个字符的移位量较小。识别这些对并交换。例如,使用上述方法:
10100100 original
10101000 candidate
--------
....!!.. two differences, one swap
10100100 original
01010100 candidate
--------
!!!!.... four differences, two swaps
您使用第一个候选项,位置4和5已经标识。将字符串转换为整数集合:
("10100100".toList).map (_.toInt-'0')
= List(1, 0, 1, 0, 0, 1, 0, 0)
使用索引将其压缩:
.zipWithIndex
List((1,0), (0,1), (1,2), (0,3), (0,4), (1,5), (0,6), (0,7))
对于模,找到索引(0,1,2…),我们期望的值,(010…)a是字符串值,b是可能的,交替值01,c是字符串中的索引
.map {case (a,b)=> (a, b%2, b)}
List((1,0,0), (0,1,1), (1,0,2), (0,1,3), (0,0,4), (1,1,5), (0,0,6), (0,1,7))
筛选符合预期的人(对顺序相反的人也一样,a!=b):
按交替值分组,以便以后计数:
.groupBy {case (a,b,c)=> b}
Map(1 -> List((1,1,5)), 0 -> List((0,0,4), (0,0,6)))
获取长度并计数:
.map {case (a, b) => (a, b.length)}
Map(1 -> 1, 0 -> 2)
忽略1和0作为标识符,只需进行计数:
.map (i => (i._2))
List(1, 2)
由于我们只能对1执行掉期交易,其中我们有相应的0,反之亦然,因此取两者中的最小值:
"10100100".toList).map (_.toInt-'0').zipWithIndex.map {case (a,b)=> (a, b%2, b)}.filter {case (a,b,c) => a==b }.groupBy {case (a,b,c)=> b}.map {case (a, b)=> (a, b.length)}.map (i => (i._2)).min
1
最后,我们不需要c值,它只是用来跟踪发生了什么。以下是不带c的版本,以1而不是0开头:
("10100100".toList).map (_.toInt-'0').zipWithIndex.map {case (a,b)=> (a, b%2)}.filter {case (a,b) => a!=b }.groupBy {_._2}.map {case (a, b)=> (a, b.length)}.map (i => (i._2)).min
2
这两个值(1,2)中的最小值就是解决方案。您有没有尝试过这个问题?即使是蛮力算法?想到的简单解决方案是
而(未排序){swap(随机元素1,随机元素2)}
,这可能在宇宙热死之前完成,也可能不完成;-)您是否必须检查10101000或01010100(第一个示例)是否需要更少的掉期?或者你必须为一些有效的解决方案寻找最少的交换吗?思考('1')的位置和模运算能帮助你吗?O(2n):解析字符串以计算0,1的数量。重写字符串,从第一个字符开始,然后交替0,1,直到一组字符用完,然后用剩余的字符结束字符串。不需要交换。@AJD发布您的答案,这是正确的方法,但唯一的操作是交换?如果我们可以list
、zip
和group
,那么我在上面的评论中提到的字符串解决方案也是可能的(因为字符串只是一个有序的字符列表)。好吧,我想这是要做的实际操作,而不是在哪里执行交换的推理。“你知道如何计算吗?”-所以问题是,如何计算互换。
("10100100".toList).map (_.toInt-'0').zipWithIndex.map {case (a,b)=> (a, b%2)}.filter {case (a,b) => a!=b }.groupBy {_._2}.map {case (a, b)=> (a, b.length)}.map (i => (i._2)).min
2