java将list拆分为三元组_java – 最佳合并三元组

这将是一个很长的答案,悲伤地没有一个最佳的解决方案(对不起).然而,对您的问题应用贪心解决问题是一个认真的尝试,因此在原则上可能是有用的.我没有实施最后讨论的方法,也许这种方法可以产生最佳解决方案 – 我不能保证.

0级:不是很贪心

根据定义,贪婪算法具有用于以局部最优的方式选择下一步骤的启发式,即现在最优化,希望达到总是可能或可能不可能的全局最优值.

您的算法选择任何可合并的对,并将其合并,然后继续.它没有评估这个合并意味着什么,以及是否有更好的本地解决方案.因为这样,我根本就不会称呼你的贪心.这只是一种解决方案,一种方法.我会把它称为盲算法,以便我可以在我的答案中简明扼要地引用它.我还将使用一个稍微修改版本的算法,而不是删除两个三元组并附加合并的三元组,只删除第二个三元组,并替换第一个合并的三元组.所得到的三元组的顺序是不同的,因此也可能是最终结果.让我在一个代表性的数据集上运行这个修改后的算法,标记一个与*的合并三元组:

0: 3 2 3 3 2 3 3 2 3

1: 0 1 0* 0 1 2 0 1 2

2: 1 2 0 1 2 0* 1 2 1

3: 0 1 2*

4: 1 2 1 1 2 1*

5: 0 2 0 0 2 0 0 2 0

Result: 4

1级:贪心

要有一个贪心的算法,您需要以允许比较选项的方式来制定合并决策,当多个可用时.对我来说,合并决策的直观表述是:

If I merge these two triplets, will the resulting set have the maximum possible number of mergable triplets, when compared to the result of merging any other two triplets from the current set?

我重复一遍,这对我来说是直观的.我没有证据表明这导致了全局最优解决方案,甚至不会导致比盲算法更好还是平等的解决方案 – 但它符合贪心的定义(而且很容易实现).让我们在上面的数据集上尝试一下,显示每个步骤之间的可能合并(通过指示三元组对的索引)和每个可能合并的合并数量:

mergables

0: 3 2 3 (1,3)->2

1: 0 1 0 (1,5)->1

2: 1 2 0 (2,4)->2

3: 0 1 2 (2,5)->2

4: 1 2 1

5: 0 2 0

除了合并三元组1和5之外,任何选择都是正确的,如果我们采用第一对,我们可以得到与盲算法相同的临时集(我将在此时缩小索引以消除差距):

mergables

0: 3 2 3 (2,3)->0

1: 0 1 2 (2,4)->1

2: 1 2 0

3: 1 2 1

4: 0 2 0

这是该算法的不同之处:它选择三元组2和4,因为与盲法算法的选择相反,在合并之后还有一个可能的合并:

mergables

0: 3 2 3 (2,3)->0 3 2 3

1: 0 1 2 0 1 2

2: 1 2 0 1 2 1

3: 1 2 1

Result: 3

2级:很贪心

现在,这种直觉启发式的第二步是向前看一个合并,然后问启发式问题.一般来说,你会展望未来,k将进一步融合并应用上述启发式,回溯性,并决定最佳选择.现在这样很详细了,所以为了举例说明,我只会用lookahead 1来执行这个新启发式的一步:

mergables

0: 3 2 3 (1,3)->(2,3)->0

1: 0 1 0 (2,4)->1*

2: 1 2 0 (1,5)->(2,4)->0

3: 0 1 2 (2,4)->(1,3)->0

4: 1 2 1 (1,4)->0

5: 0 2 0 (2,5)->(1,3)->1*

(2,4)->1*

标有星号的合并序列是应用此新启发式的最佳选择.

如果需要口头解释:

Instead of checking how many merges are possible after each possible merge for the starting set; this time we check how many merges are possible after each possible merge for each resulting set after each possible merge for the starting set. And this is for lookahead 1. For lookahead n, you’d be seeing a very long sentence repeating the part after each possible merge for each resulting set n times.

3级:让我们切开贪心

如果仔细观察,以前的方法对于甚至适度的投入和前瞻性(*)来说都具有灾难性的表现.对于超过20个三元组的输入,任何超过4合并 – 前瞻性的任何时间都不合时宜.这里的想法是删除似乎比现有解决方案更差的合并路径.如果我们要执行前瞻10,并且特定的合并路径在三次合并之后产生较少的合并,比5次合并之后的另一个路径,我们可以同样剪切当前的合并路径并尝试另一个路径.这应该节省很多时间,并允许大量的前瞻,这将使我们更接近全球最佳解决方案,希望.我还没有实施这个测试.

(*): Assuming a large reduction of input sets is possible, the number of merges is

proportional to input size, and

lookahead approximately indicates how much you permute those merges.

So you have choose lookahead from |input|, which is

the binomial coefficient that for lookahead ≪ |input| can be approximated as

O(|input|^lookahead) — which is also (rightfully) written as you are thoroughly screwed.

把它们放在一起

我对这个问题很感兴趣,我在Python中坐下来编码.可悲的是,我能够证明不同的前瞻可能会产生不同的结果,即使盲法也偶尔比前瞻1或2更好.这是解决方案不是最佳的直接证明(至少对于前瞻«|输入|).请注意,除了合并结果的记录外,我没有尝试以CPU循环方式优化代码.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值