假设有一个2D数组(m x n)
位。
例如:
1 0 0 1 0
1 0 1 0 0
1 0 1 1 0
0 0 0 0 1
此处m = 4
,n = 5
。
我可以翻转(0
变为1
,1
变为0
)任意行中的位。当您翻转特定行中的位时,将翻转 all 位。
我的目标是在给定的一对行之间获得最大OR
值。
也就是说,如果给定的行对是(r1, r2)
,那么我可以在r1
和r2
之间翻转任意数量的行,我应该找到最大可能{{1} OR
和r1
之间所有行的值。
在上面的示例中(考虑具有从1开始的索引的数组),如果r2
= 1且r1
= 4,我可以翻转第1行以获得r2
。现在,如果我找到从1到4的所有行的0 1 1 0 1
值,我会将值OR
作为最大可能的31
值(可以有其他解决方案)。
此外,计算OR
,(r1, r1)
,(r1, r1+1)
,...,(r1, r1+2)
的答案,同时为{{1 }}
约束
(r1, r2-1)
(r1,r2)
简单的蛮力解决方案的时间复杂度为1 <= m x n <= 10^6
。
有更快的计算方法吗?
答案 0 :(得分:0)
从A <= A | B
开始,数字A的值只会随着OR
个数字增加到A而增加。
因此,我们可以使用二分搜索。
我们可以使用函数来获取两行之间的最大值,并将OR
ed结果保存为第三行。然后比较这些第三行中的两行以获得更高级别的行,然后比较其中两个更高级别的行,依此类推,直到只留下一行。
使用您的示例:
array1 = 1 0 0 1 0 [0]
1 0 1 0 0 [1]
1 0 1 1 0 [2]
0 0 0 0 1 [3]
array2 = 1 1 0 1 1 <-- [0] | ~[1]
1 1 1 1 0 <-- [2] | ~[3]
array3 = 1 1 1 1 1 <-- [0] | [1]
显然,当m
不是2的幂时,你可以根据需要截断分支。
所以这将是O(m)
时间。请记住,对于大量行,可能没有唯一的解决方案。结果很可能是2 ^ n - 1
。
重要优化:如果m >= n
,则输出必须为2 ^ n - 1
。假设我们有两个数字A和B.如果B有k
个数字缺失位,那么A
或~A
将保证至少填充其中一个位。通过类似的标记,如果m >= log n
,那么输出也必须是2 ^ n - 1
,因为每个A
或~A
都可以保证填充{{1}中至少一半的未填充位1}}。
使用这些快捷方式,您可以根据需要进行强力搜索。我不是100%二进制搜索算法适用于每一种情况。
答案 1 :(得分:0)
考虑到在整个矩阵中翻转行然后将它们放在一起以获得尽可能多的1的问题,我声称当列数小于2 ^ m时这是易处理的,其中m是行数。逐行考虑行。在阶段i从0开始计数,你需要填充少于2 ^(m-i)个零。因为翻转行将0变为1,反之亦然,当前行或翻转行将填充这些零中的至少一半。当您完成所有行后,您将填充少于1个零,因此保证此过程可以提供完美的答案。
我声称当列数至少为2 ^ m时,这是易处理的,其中m是行数。有两个可能的翻转行模式,但这只是O(N),其中N是列数。因此,在这种情况下,尝试所有可能的翻转行模式会为您提供O(N ^ 2)算法。