Redian新闻
>
一道面试题:三等分数组
avatar
一道面试题:三等分数组# JobHunting - 待字闺中
d*r
1
一道面试题:
给定一个整数数组。怎样能将其分为三组(不要求个数相等),使每组值的总和相等。
不能分的时候返回空值。能分的时候给出一个解就行。
我只能想到三进制,有没有更优化的方法?
avatar
c*t
2
是整数吧?要求每组的整数个数相等吗?

【在 d****r 的大作中提到】
: 一道面试题:
: 给定一个整数数组。怎样能将其分为三组(不要求个数相等),使每组值的总和相等。
: 不能分的时候返回空值。能分的时候给出一个解就行。
: 我只能想到三进制,有没有更优化的方法?

avatar
d*r
3
对,整数。有何高见?

【在 c********t 的大作中提到】
: 是整数吧?要求每组的整数个数相等吗?
avatar
j*y
4
用三进制 brute force ?

【在 d****r 的大作中提到】
: 对,整数。有何高见?
avatar
d*r
5
我是那么想的。三进制达不到要求。要求优化解。

【在 j*****y 的大作中提到】
: 用三进制 brute force ?
avatar
d*r
6
不要求个数相等。

【在 c********t 的大作中提到】
: 是整数吧?要求每组的整数个数相等吗?
avatar
j*y
7
二等分数组是可以用 dp的,
三等分的话,可不可以证明:
如果可以三等分的话,如果拿出一个子集的和是 1/3的和,那么剩下的一定可以二等分?
这个可以证明是正确的话,那么就是两次 dp 了

【在 d****r 的大作中提到】
: 一道面试题:
: 给定一个整数数组。怎样能将其分为三组(不要求个数相等),使每组值的总和相等。
: 不能分的时候返回空值。能分的时候给出一个解就行。
: 我只能想到三进制,有没有更优化的方法?

avatar
j*y
8
这个可以证明是正确的,那么就是两次 dp
第一次 dp 找出和是 1/3 的总和的子集
第二次dp 等分剩下的集合

分?

【在 j*****y 的大作中提到】
: 二等分数组是可以用 dp的,
: 三等分的话,可不可以证明:
: 如果可以三等分的话,如果拿出一个子集的和是 1/3的和,那么剩下的一定可以二等分?
: 这个可以证明是正确的话,那么就是两次 dp 了

avatar
z*8
9
我觉得这个思路挺好,有点递归的意思,不过条件有点强吧。
比如
1,2,3,
0,0,5,
0,0,7
这个数组就是不能三分的。

分?

【在 j*****y 的大作中提到】
: 二等分数组是可以用 dp的,
: 三等分的话,可不可以证明:
: 如果可以三等分的话,如果拿出一个子集的和是 1/3的和,那么剩下的一定可以二等分?
: 这个可以证明是正确的话,那么就是两次 dp 了

avatar
j*y
10
不能三分的话两次 dp 也能 detect 出来

【在 z*******8 的大作中提到】
: 我觉得这个思路挺好,有点递归的意思,不过条件有点强吧。
: 比如
: 1,2,3,
: 0,0,5,
: 0,0,7
: 这个数组就是不能三分的。
:
: 分?

avatar
c*t
11
应该不是正确的。1,1,3,4,6
dp 两次也不一定可以 1,1,2,3,4,4 如果第一次拿走 1,1,3,以后将无解啊

【在 j*****y 的大作中提到】
: 这个可以证明是正确的,那么就是两次 dp
: 第一次 dp 找出和是 1/3 的总和的子集
: 第二次dp 等分剩下的集合
:
: 分?

avatar
j*y
12
哈哈,我刚才大脑过了一遍,感觉是对的,看来是错的 :)

【在 c********t 的大作中提到】
: 应该不是正确的。1,1,3,4,6
: dp 两次也不一定可以 1,1,2,3,4,4 如果第一次拿走 1,1,3,以后将无解啊

avatar
c*t
13
用dp找出=1/3*sum 的所有解,然后对每一组都取剩下的,试试能不能用dp 2等分?
是不是太复杂了?

【在 j*****y 的大作中提到】
: 哈哈,我刚才大脑过了一遍,感觉是对的,看来是错的 :)
avatar
j*y
14
这个所有解,感觉太复杂了:)

【在 c********t 的大作中提到】
: 用dp找出=1/3*sum 的所有解,然后对每一组都取剩下的,试试能不能用dp 2等分?
: 是不是太复杂了?

avatar
f*e
15
一个DP就行,然后就看所有解中是否有两个不相交就行。

【在 c********t 的大作中提到】
: 用dp找出=1/3*sum 的所有解,然后对每一组都取剩下的,试试能不能用dp 2等分?
: 是不是太复杂了?

avatar
c*t
16
嗯,同意

【在 f*****e 的大作中提到】
: 一个DP就行,然后就看所有解中是否有两个不相交就行。
avatar
d*n
17
不可以,有反例

分?

【在 j*****y 的大作中提到】
: 二等分数组是可以用 dp的,
: 三等分的话,可不可以证明:
: 如果可以三等分的话,如果拿出一个子集的和是 1/3的和,那么剩下的一定可以二等分?
: 这个可以证明是正确的话,那么就是两次 dp 了

avatar
d*n
18
请大牛明示,这道题的dp是找一个解吧?用一个二维数组来储存当前element可能生成
的和

【在 f*****e 的大作中提到】
: 一个DP就行,然后就看所有解中是否有两个不相交就行。
avatar
s*i
19
这道题不是经典的NP-COMPLETE的problem之一么...还解个啥?
avatar
t*a
20
我把它当二维DP做了,clojure程序和结果如下
(def divide-3-sub
(memoize
(fn [s1 s2 [x & xs]]
(cond (and (zero? s1) (zero? s2)) ['() '() (cons x xs)]
(or (< s1 0) (< s2 0) (empty? xs)) nil
:else (if-let [d1 (divide-3-sub (- s1 x) s2 xs)]
(assoc d1 0 (cons x (first d1)))
(if-let [d2 (divide-3-sub s1 (- s2 x) xs)]
(assoc d2 1 (cons x (second d2)))
(if-let [d3 (divide-3-sub s1 s2 xs)]
(assoc d3 2 (cons x (last d3)))
nil)))))))
(defn divide-3 [x]
(let [s (apply + x)
s3 (int (/ s 3))]
(if (= s (* s3 3))
(divide-3-sub s3 s3 x)
nil)))
(divide-3 (take 12 (repeat 1))) ; [(1 1 1 1) (1 1 1 1) (1 1 1 1)]
(divide-3 (range 6)) ; [(0 1 4) (2 3) (5)]
(divide-3 (range 12)) ; [(0 1 2 3 7 9) (4 8 10) (5 6 11)]
(divide-3 (take 100 (repeatedly #(rand-int 20)))) ; [(19 19 5 19 3 3 7 4 2 4
18 5 16 9 4 16 7 3 12 9 3 19 2 6 13 5 0 3 0 9 3 7 12 8 17 1 7 9 17 1 0 0 0)
(17 18 17 12 19 4 9 18 5 17 3 14 19 16 7 7 1 8 3 14 4 10 19 15 4 15 17 13 1
) (16 15 10 19 6 17 11 15 18 18 14 8 17 11 17 9 19 6 5 2 2 11 7 11 19 15 5 3
)]
这个程序的计算复杂度为O(s*s*n),其中s为数组的总和,n为数组长度。
avatar
j*y
21
能把那个 optimal structure 写一下吗?
thanks.

【在 t****a 的大作中提到】
: 我把它当二维DP做了,clojure程序和结果如下
: (def divide-3-sub
: (memoize
: (fn [s1 s2 [x & xs]]
: (cond (and (zero? s1) (zero? s2)) ['() '() (cons x xs)]
: (or (< s1 0) (< s2 0) (empty? xs)) nil
: :else (if-let [d1 (divide-3-sub (- s1 x) s2 xs)]
: (assoc d1 0 (cons x (first d1)))
: (if-let [d2 (divide-3-sub s1 (- s2 x) xs)]
: (assoc d2 1 (cons x (second d2)))

avatar
t*a
22
f(s1, s2, (x & xs)) = f(s1-x, s2, xs) or f(s1, s2-x, xs) or f(s1, s2, xs)
f(0, 0, (x & xs)) 时候成功
话说楼主的3进制是什么意思啊?
avatar
j*y
23
s1 是第一个 subset, s2 是第二个 subset ?
x 和 xs 是什么呢?

【在 t****a 的大作中提到】
: f(s1, s2, (x & xs)) = f(s1-x, s2, xs) or f(s1, s2-x, xs) or f(s1, s2, xs)
: f(0, 0, (x & xs)) 时候成功
: 话说楼主的3进制是什么意思啊?

avatar
t*a
24
(x & xs)整体表示输入的数字序列。s1是该数字序列中需要分出来第一组的和和第二组
的和。本题s1=s2=1/3 * sum(x & xs)

【在 j*****y 的大作中提到】
: s1 是第一个 subset, s2 是第二个 subset ?
: x 和 xs 是什么呢?

avatar
w*o
25
小弟抛块砖,希望大牛们点评下。
首先sort, 从大到小排列。
L: 100, 98, 97, 76, 50, 30, ...., 10, 9, 2,1
分3组, a, b, c. 挨个拿。
First time
a: 100
b: 98
c: 97
sum(a) = 100
sum(b) = 98
sum(c) = 97 最小, 把L里面最大的分给他
Second time
a: 100,
b: 98,
c: 97, 76
sum(a) =100
sum(b) = 98 最小, 把L里面最大的分给他
sum(c) =173
3rd
a: 100,
b: 98, 50,
c: 97, 76,
sum(a) =100 最小, 把L里面最大的分给他
sum(b) = 148
sum(c) = 173
3rd
a: 100, 30
b: 98, 50,
c: 97, 76,
以此类推, 全部分完。
这样3组的difference比较小,size基本一样的情况下。
算法:个人理解就和国内分蛋糕一样。
每人都拿一块, c拿最小的要说话了, 再给我一份。
c变最大, b说他也要,一次不行,两次,拿到他是最大的(最小的变最大的)。
接着a也不服气,直到大家找到平衡点(找到组合), 要么掀桌
子(return null)。
可用structure,: 2个heap, one min heap for 3(a,b,c), one max heap for list(
same thing as sorted list)。
====
回复楼上,估计不是测试DP问题,interviewer没那个闲工夫测试30mins吧。
avatar
t*a
26
这个会挂掉的。因为解的个数在最糟糕情况下是个组合数。

【在 f*****e 的大作中提到】
: 一个DP就行,然后就看所有解中是否有两个不相交就行。
avatar
t*a
27
这样的方法好像是贪婪,不知道能不能保证找到结果啊。我数学不好,有哪位朋友来证
明一下贪婪对不对么?

【在 w**********o 的大作中提到】
: 小弟抛块砖,希望大牛们点评下。
: 首先sort, 从大到小排列。
: L: 100, 98, 97, 76, 50, 30, ...., 10, 9, 2,1
: 分3组, a, b, c. 挨个拿。
: First time
: a: 100
: b: 98
: c: 97
: sum(a) = 100
: sum(b) = 98

avatar
w*o
28
题目本身是NP, 所以应该没问题吧。
希望PeK能点评下。

【在 t****a 的大作中提到】
: 这样的方法好像是贪婪,不知道能不能保证找到结果啊。我数学不好,有哪位朋友来证
: 明一下贪婪对不对么?

avatar
d*x
29
http://poj.org/problem?id=1011
一个区别不大的问题,poj的这个只是组数不确定
如果没记错的话,没有多项式解法,只是暴力搜索,加上各种神奇的剪支。

【在 d****r 的大作中提到】
: 一道面试题:
: 给定一个整数数组。怎样能将其分为三组(不要求个数相等),使每组值的总和相等。
: 不能分的时候返回空值。能分的时候给出一个解就行。
: 我只能想到三进制,有没有更优化的方法?

avatar
s*i
30

我都说了是NP-COMPLETE了,为什么大家都无视我呢... T_T

【在 d**********x 的大作中提到】
: http://poj.org/problem?id=1011
: 一个区别不大的问题,poj的这个只是组数不确定
: 如果没记错的话,没有多项式解法,只是暴力搜索,加上各种神奇的剪支。

avatar
d*x
31
真没看见你那篇。。

【在 s********i 的大作中提到】
:
: 我都说了是NP-COMPLETE了,为什么大家都无视我呢... T_T

avatar
f*e
32
对NP-complete,你能搞个pseudopolynoimal算法,也很nb的。

【在 s********i 的大作中提到】
:
: 我都说了是NP-COMPLETE了,为什么大家都无视我呢... T_T

avatar
v*e
33
既然是np complete 为啥还要考楼主算法和优化解?

【在 s********i 的大作中提到】
:
: 我都说了是NP-COMPLETE了,为什么大家都无视我呢... T_T

avatar
s*r
34
这个不就是相当于leetcode上的combination sum么?
target = total_sum/3
如果能找两个不相交的组合就可以了

【在 d****r 的大作中提到】
: 一道面试题:
: 给定一个整数数组。怎样能将其分为三组(不要求个数相等),使每组值的总和相等。
: 不能分的时候返回空值。能分的时候给出一个解就行。
: 我只能想到三进制,有没有更优化的方法?

avatar
d*x
35
Once I was interviewed by fb and the interviewer told me the problem IS an
NP, but he still wanted to see how optimized algorithm I could give

【在 v*******e 的大作中提到】
: 既然是np complete 为啥还要考楼主算法和优化解?
avatar
d*r
36

穷举。N个数的话,用N位的三进制。从0扫到最大值。0,1,2对应三个组。我这个方法实
际上没什么用。

【在 t****a 的大作中提到】
: f(s1, s2, (x & xs)) = f(s1-x, s2, xs) or f(s1, s2-x, xs) or f(s1, s2, xs)
: f(0, 0, (x & xs)) 时候成功
: 话说楼主的3进制是什么意思啊?

avatar
b*e
37
my solution: 4d np.
recursive function.
Exist(i, a1, a2, a3) = { Exist(i-1, a1-xi, a2, a3) ||
Exist(i-1, a1, a2-xi, a3) ||
Exist(i-1, a1, a2, a3-xi) }
where xi is the ith integer.
a1, a2, a3 are the sum of three subsets in the set.
start from i = 1, a1, a2, a3 = 1
stop at i = n, a1 = a2 = a3 = sum/3.
complexity n * (sum/3)^3.
Any problem with the above DP?

【在 d****r 的大作中提到】
:
: 穷举。N个数的话,用N位的三进制。从0扫到最大值。0,1,2对应三个组。我这个方法实
: 际上没什么用。

avatar
c*t
38
两个问题
1.如何保证同一个元素没有被a1,a2,a3重用
2.a3需要吗?如果能求出a1,a2就不用a3了吧。n * (sum/3)^2.

【在 b*******e 的大作中提到】
: my solution: 4d np.
: recursive function.
: Exist(i, a1, a2, a3) = { Exist(i-1, a1-xi, a2, a3) ||
: Exist(i-1, a1, a2-xi, a3) ||
: Exist(i-1, a1, a2, a3-xi) }
: where xi is the ith integer.
: a1, a2, a3 are the sum of three subsets in the set.
: start from i = 1, a1, a2, a3 = 1
: stop at i = n, a1 = a2 = a3 = sum/3.
: complexity n * (sum/3)^3.

avatar
f*s
39
背包问题也是npc啊,

【在 s********i 的大作中提到】
:
: 我都说了是NP-COMPLETE了,为什么大家都无视我呢... T_T

avatar
c*t
40
肯定是不行的
试试用你的做法把 1 3 4 5 6 7分成两组

【在 w**********o 的大作中提到】
: 小弟抛块砖,希望大牛们点评下。
: 首先sort, 从大到小排列。
: L: 100, 98, 97, 76, 50, 30, ...., 10, 9, 2,1
: 分3组, a, b, c. 挨个拿。
: First time
: a: 100
: b: 98
: c: 97
: sum(a) = 100
: sum(b) = 98

avatar
b*e
41
for (2): you are right.
recursive fucntion:
exist(i, a1, a2) = { exist(i-1, a1-xi, a2) ||
exist(i-1, a1, a2-xi)}
starting form i = 1 a1 = 1, a2 =1
end at i = n and a1 = a2 = sum/3.
complexity: n * (sum/3)^2.
don't quite understand (1). any example?
when start froming i = 1 to i = n, the recursive structure ... should be
able to gurantee that xi will only be used for once?
my solution: 3d np.
avatar
c*t
42
for 1) example 4,6.....
exist(1,10,10)= exist(0,4,10)|| exist(0,10,4);
did ur program put 4 in a1, a2 or both? how about 6?
for 1,3,4,6,1,9, how can you prevent the result to be 1,9| 1,3,6 | 4,6 (use
6 twice)

【在 b*******e 的大作中提到】
: for (2): you are right.
: recursive fucntion:
: exist(i, a1, a2) = { exist(i-1, a1-xi, a2) ||
: exist(i-1, a1, a2-xi)}
: starting form i = 1 a1 = 1, a2 =1
: end at i = n and a1 = a2 = sum/3.
: complexity: n * (sum/3)^2.
: don't quite understand (1). any example?
: when start froming i = 1 to i = n, the recursive structure ... should be
: able to gurantee that xi will only be used for once?

avatar
b*e
43
for i == 0, only exist(0, 4, 0) and exist(0, 0, 4) = true. all other
comibinations for i == 0 including exist(0, 4, 10) = false and exist(0, 10,
4) = false, so exist(1, 10, 10) = false.
for i == 1, exist(1, 10, 0) = exist(0, 4, 0 ) || exist(0, 10, -6) = true ||
false. and exist(1, 0, 10) = exist(0, -6, 10) || exist(0, 0, 4) = false ||
true and exist(1, 4, 6) = exist(0, 4, 0) || exist(0, -2, 0) = true || false
and
exist (1, 6, 4) = exist(0, 0, 4) || exist(0, 6, -2) = true || false will be
true. All other combinations will be false.
for 1, 3, 4, 5, 1, 9, "6" participate in the selection only when i == 3. and
it will either stay with 3 and 1, or with 4 for exist(3, 10, 10).
exist(3, 10, 10) = exist(2, 4, 10) || exist(2, 10, 4) = exist(1, 0, 10) ||
exist(1, 4, 6) || exist(1, 6, .... = false.

use

【在 c********t 的大作中提到】
: for 1) example 4,6.....
: exist(1,10,10)= exist(0,4,10)|| exist(0,10,4);
: did ur program put 4 in a1, a2 or both? how about 6?
: for 1,3,4,6,1,9, how can you prevent the result to be 1,9| 1,3,6 | 4,6 (use
: 6 twice)

avatar
c*t
44
I think it will cause the problem,if continuing, later 4 might be used in
both a1 and a2.
let me simplify my second example to 6,1,3,4,10. By running ur program to
get exist(3,10,10), won't 6 be used in both a1 and a2? exist(3,[6,1,3], [6,
4])?

,
|
|

【在 b*******e 的大作中提到】
: for i == 0, only exist(0, 4, 0) and exist(0, 0, 4) = true. all other
: comibinations for i == 0 including exist(0, 4, 10) = false and exist(0, 10,
: 4) = false, so exist(1, 10, 10) = false.
: for i == 1, exist(1, 10, 0) = exist(0, 4, 0 ) || exist(0, 10, -6) = true ||
: false. and exist(1, 0, 10) = exist(0, -6, 10) || exist(0, 0, 4) = false ||
: true and exist(1, 4, 6) = exist(0, 4, 0) || exist(0, -2, 0) = true || false
: and
: exist (1, 6, 4) = exist(0, 0, 4) || exist(0, 6, -2) = true || false will be
: true. All other combinations will be false.
: for 1, 3, 4, 5, 1, 9, "6" participate in the selection only when i == 3. and

avatar
b*e
45
exist(3, 10, 10)
= exist(2, 10-4, 10) || exist(2, 10, 10-4)
= exist(2, 6, 10) || exist(2, 10, 6) = false || false = false already.
let us continue from i == 2 to i== 1
= exist(1, 3, 10) || exist(1, 6, 7) || exist(1, 7, 6) || exist(1, 6, 7)
= false || false || false || false.
we can continue from i == 1 to 0.
also we can find it is false.
So exist(3, 10, 10) = false. That indicates 6 are not used for multiple
times.
Otherwise exist(3, 10, 10) should be true.

to
6,

【在 c********t 的大作中提到】
: I think it will cause the problem,if continuing, later 4 might be used in
: both a1 and a2.
: let me simplify my second example to 6,1,3,4,10. By running ur program to
: get exist(3,10,10), won't 6 be used in both a1 and a2? exist(3,[6,1,3], [6,
: 4])?
:
: ,
: |
: |

avatar
c*t
46
好像你是对的。我有空做做看。多谢!

【在 b*******e 的大作中提到】
: exist(3, 10, 10)
: = exist(2, 10-4, 10) || exist(2, 10, 10-4)
: = exist(2, 6, 10) || exist(2, 10, 6) = false || false = false already.
: let us continue from i == 2 to i== 1
: = exist(1, 3, 10) || exist(1, 6, 7) || exist(1, 7, 6) || exist(1, 6, 7)
: = false || false || false || false.
: we can continue from i == 1 to 0.
: also we can find it is false.
: So exist(3, 10, 10) = false. That indicates 6 are not used for multiple
: times.

avatar
b*e
47
This is a problem in DP chapter of "Algorithms" by a berkeley professor. It
asked for a polynomail complexity solution whether dividing evenly by 3
exists or not.

【在 d****r 的大作中提到】
: 一道面试题:
: 给定一个整数数组。怎样能将其分为三组(不要求个数相等),使每组值的总和相等。
: 不能分的时候返回空值。能分的时候给出一个解就行。
: 我只能想到三进制,有没有更优化的方法?

相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。