十年程序员难倒了一个算法上面,真的老了

2022-11-15 17:40:20 +08:00
 diandian666

如题,各位大佬摸鱼的时间看看怎么解决!!感谢! 感恩!思密达!

公司业务需要,把我难倒了。各位大佬看看能不能摸鱼的时间来看看这个需求。代码递归跑的内存都溢出了,万分感谢。

题目:

有两组数字数组数据,数组 1 的数据的总和 = 数组 2 数据的总和。数组 1 的数量 <= 数组 2 的数量。且数组 1 中每一个数字都可以对应数组 2 中 N 个数字的和。找出数组 1 中的数字对应数组 2 中的数据。不能重复使用。 注:不用担心匹配不上的情况,这两组数据都是有根据出来的,绝对能匹配成功,之前都是人工匹配的,现在想用代码直接取代人工。

题目说的有点不清楚,举例:

数组 1: [62.13,26.67,17.76]

数组 2:[24.92,5.88,5.04,3.64,3.45,3.36,2.8,2.8,2.52,2.24,2.24,2.24,1.96,1.96,1.8,1.68,1.4,1.4,1.4,1.2,1.2,1.15,1.12,1.12,1.12,1.12,1.12,0.84,0.84,0.84,0.84,0.84,0.84,0.84,0.84,0.84,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.4,0.4,0.4,0.4,0.4,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28]

最终需要匹配出来结果

62.13=>[24.92,5.88,5.04,3.64,3.45,2.8,2.8,2.52,2.24,2.24,2.24,1.96,1.2,1.2],

26.67=>[1.96,1.68,1.4,1.15,1.12,1.12,0.84,0.84,0.84,0.84,0.84,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.4,0.4,0.4,0.4,0.4,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28]

17.76=>[3.36,1.8,1.4,1.4,1.12,1.12,1.12,0.84,0.84,0.84,0.84,0.56,0.56,0.56,0.56,0.56,0.28]

上面就是匹配的结果。

我这边多提供两组数据供测试,下面的两组测试成功的话,再尝试上面提到的那组数据,毕竟上面那组数据多,影响测试

第一组:

数组 1 [52.7,8.96]

数组 2 [21.44,6.72,5.44,5.12,4.48,3.20,2.24,1.92,1.92,1.92,1.28,1.28,1.00,0.96,0.50,0.32,0.32,0.32,0.32,0.32,0.32,0.32]

第二组:

数组 1 [23.17,3.2,1.22,0.32]

数组 2 [7.36,4.16,3.20,1.69,1.28,1.28,0.96,0.96,0.90,0.64,0.64,0.64,0.50,0.50,0.32,0.32,0.32,0.32,0.32,0.32,0.32,0.32,0.32,0.32

]

25985 次点击
所在节点    程序员
207 条回复
SimonOne
2022-11-16 11:24:12 +08:00
@Damn #136 兄弟能具体说下是哪条回复吗,因为每个人的 block 名单都不一样,所以楼层数大家应该都不一样的
diandian666
2022-11-16 11:29:52 +08:00
@maggch97
前面回复的那组不成功的数据。因为数据有其他同类型元素可以合并起来,我这边可以合并的数据数据是下面,合并后的能成功出结果。

数组 1:
[21.04,15.08,2.52]

数组 2:
[3.36,3.36,2.52,1.68,1.68,1.40,1.40,1.40,0.84,0.84,0.84,0.84,0.84,0.84,0.84,0.80,0.80,0.80,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.40,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28]
penzi
2022-11-16 11:33:11 +08:00
@Damn 我知道 NP ,但是如果人手都能凑出来说明数据保证了凑出解的概率非常大。凑数字这种人脑根本没优势的项目,机器不可能比人差。


@diandian666 我代码确实还有些问题,sort 都是错的,还有重复搜索的问题。但是回到你这个问题,你这组数据凑不出解的。只有一个 0.4 但是 1.52 和 0.96 凑出来都需要 0.4
0.96 = 0.4+0.28*2
1.54 = 0.28*4+0.4
只有上面一种凑法
maplelin
2022-11-16 11:39:43 +08:00
感觉这种具体业务的数据,如果有些其他关联性的结论用来剪枝就好了,毕竟人工可以得出解,算法的话应该有技巧可以优化的。
diandian666
2022-11-16 11:43:03 +08:00
@maggch97 这组数据其实还有其他数据的。只是我在两个数组中,去掉两个数组都一样的值剩下的。估计我的数据确实是需要把相同属性的合并起来在匹配。后面已经贴出来没有去除两个数组相同的值且把数组 1 相同属性的合并起来后,再用你的代码匹配。确实成功了。真不错。666 啊
penzi
2022-11-16 11:50:25 +08:00
@diandian666 去掉相同的这个优化没有问题,问题是你的 1 数据不合并可能根本凑不出解
Damn
2022-11-16 11:52:33 +08:00
diandian666
2022-11-16 11:52:59 +08:00
@maggch97 我这边也顺便贴出来没有合并数组 1 前的数据数据。看大佬有没有兴趣研究,不排除我的数据是一定需要合并才能匹配,因为原题那三组数据的数组 1 确实是我合并后的,因为合并数组 1 后,能匹配出来。也能解决问题了。

数组 1:
[2.52,11.4,0.56,9.08,8.4,1.4,0.84,0.96,1.68,1.52,0.28]

数组 2:
[3.36,3.36,2.52,1.68,1.68,1.40,1.40,1.40,0.84,0.84,0.84,0.84,0.84,0.84,0.84,0.80,0.80,0.80,0.56,0.56,0.56,0.56,0.56,0.56,0.56,0.40,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28,0.28]
diandian666
2022-11-16 11:53:55 +08:00
@maggch97 哈哈,对的。我现在也怀疑这个,因为原题给的几组都是合并数组 1 的。
penzi
2022-11-16 11:56:45 +08:00
@diandian666 我上面说了,你 2 数组里只有一个 0.4 是凑不出 1 数组里的 0.96 和 1.52 的。你手算试试用 2 数组里面的数字去凑凑看,能不能凑出这两个数字
A3
2022-11-16 12:01:01 +08:00
@EugeneYWang 我不是面试官🙈
haichaofine32
2022-11-16 12:16:31 +08:00
好奇,这题能否反过来做?也就是给定一个数组,取任意个数值相加,看能得出多少不同的结果?猜测循环次数应该是折半的,例如九个数任取两个不重复,和九个数任取 7 个不重复是一个种状态。非专业,大佬忽喷
diandian666
2022-11-16 12:20:08 +08:00
@maggch97 似乎还真是。大佬 666 ,
Innovatino
2022-11-16 12:38:00 +08:00
@diandian666 建议买杯咖啡给大佬🤣
sdushn
2022-11-16 14:01:51 +08:00
回溯?
14104chk
2022-11-16 14:22:44 +08:00
bosskwei
2022-11-16 14:41:39 +08:00
你这个问题很简单,实际上可以认为是一个近似矩阵乘法的操作。矩阵的 element 只有 0 或 1
lyminghao
2022-11-16 15:01:04 +08:00
相当于迭代地求解 subset sum 问题( 0-1 背包的一个变体),是 NP 完全的。

当然自己写个搜索算法也 ok ,但是像这种难度的问题,还是建议试下用求解器解决。比如建模成一个 0-1 整数规划问题,送进 CPLEX ,Gurobi 直接就有答案了。

如果人肉眼都能配出解来,那对这些求解器肯定是能秒出结果的。
lyminghao
2022-11-16 15:09:00 +08:00
@optional 很简单啊,设数组一为 A ,数组二为 B ;布尔变量 x[i,j]表示 B[j]匹配到 A[i];
约束:
forall (i in 1...|A|) (sum (j in 1...|B|) (x[i,j] * B[j]) == A[i]); // 满足求和要求
forall (j in 1...|B|) (sum (i in 1...|A|) (x[i,j]) == 1); // B 到 A 匹配唯一
mylove614
2022-11-16 15:15:49 +08:00
建议发在 icpc 或者 oi 的群里,大佬应该会给你答案的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/895464

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX