二进制数组,面试问题

时间:2016-05-25 18:07:29

标签: java arrays algorithm binary-data

我一直在练习一些java面试编码问题,我在下面遇到了这个问题。

  

给定一个包含N个元素的整数数组:d [0],d [1],... d [N -   1]。您可以在阵列上执行AT MOST一次移动:选择任意两个   整数[L,R],并翻转(包括)之间的所有元素   第L和第R位。 L和R代表最左侧和最右侧   标记您所在段的边界的位的索引   决定翻转。

     

您可以使用' 1' -bits(由S表示)的最大数量是多少   获取最终的位串?

     

'翻转'有点意味着,0转换为1,1为1   变换为0(0-> 1,1-> 0)。输入格式整数N下一行   包含N位,用空格分隔:d [0] d [1] ... d [N - 1]

在下面的部分中,使用示例解释了问题,但我无法理解示例的结果。这里的问题是我应该首先理解这个问题,然后我可以尝试解决问题。

  

给出的解决方案:

     

输出:S

     

约束:1&lt; = N&lt; = 100000 d [i]只能是0或1 0 <= L <= R&lt;   n

     

样本输入:8 1 0 0 1 0 0 1 0

     

样本输出:6

     

说明:

     

通过执行,我们可以在给定的二进制数组中获得最多6个   以下任一操作:翻转[1,5] ==&gt; 1 1 1 0 1 1 1 0

我不知道样本输出是6以及如何在给定的二进制数组中最多获得6个。

有人可以帮助我理解。我知道它的东西很简单,但不知怎的,我得不到它。

谢谢!

2 个答案:

答案 0 :(得分:1)

让我们从这里开始:

  

在下面的部分中,使用示例解释了问题,但我无法理解示例的结果。这里的问题是我应该首先理解这个问题,然后我可以尝试解决这个问题。

您正尝试在连续范围内应用单个位移操作,其目标是最大化阵列中1的数量。

查看我们的8号样本输入

1 0 0 1 0 0 1 0

我们注意到有5 0&#39。为了对我的思维过程进行超级总结,真正的问题是确定一个有点翻转的范围将为你带来最大的积极变化,换句话说,&#34;找到一个具有最多0和最小1&的范围#39; S&#34;

我们查看示例输入并看到位0是1,所以我们已经排除了它。第1位和第2位是0,这迫使我们将它放在我们的范围内。位3是1,但接下来的两位,位4和5是零,这意味着包括位3,4和5将具有净增益。看第6和第7位,他们相互取消&#34;,意味着包括它们或排除它们并不重要。

所以为了把它包起来,我们的范围从第1位开始,以第5位(包含)结束。

翻转后,我们离开了

1 1 1 0 1 1 1 0

或6 1​​&#39; s,即样本输出

请随意留下任何问题。这种方法是一种人性化的方法。我们可以用这么小的输入大小做。编写一个算法来找到最佳范围,在手动完成一个小样本后,会有更多的步骤。

答案 1 :(得分:1)

暂时忘记数组,你有二进制数:

1 0 0 1 0 0 1 0

你的任务是找到左右索引,例如:

1 0 0 1 0 0 1 0
  ^       ^
  left    right

当你反转左/右之间的每一位并计算最终数字/数组中的数目(1)时,找到最大数量为1的左/右索引的组合

在这个特定的例子中,如果我们采用左1,右5,最终数组将是

0 1 2 3 4 5 6 7 (indexes)
1 0 0 1 0 0 1 0 (original array)
1 1 1 0 1 1 1 0 (I've inverted, 1st, 2nd, 3rd, 4th, 5th)

现在,我们如何计算它。第一种方法通常是蛮力,尝试所有可能的左/右组合并找到最大值:

public static void main(final String s[]) {
    final int[] d = {1, 0, 0, 1, 0, 0, 1, 0};
    int max = getOnes(d);
    for (int left = 0; left < (d.length - 1); left++) {
        for (int right = (left + 1); right < d.length; right++) {
            invert(d, left, right); // flip bits
            max = Math.max(max, getOnes(d));
            invert(d, left, right); // reverse flipping
        }
    }
    System.out.println(max);
}

static int getOnes(final int[] d) {
    int cnt = 0;
    for (final int i : d) cnt += i;
    return cnt;
}

static void invert(final int[] d, final int left, final int right) {
    for (int i = left; i <= right; i++) d[i] = (1 - d[i]);
}

下一步是优化此解决方案,这里有几个提示:

  1. 左索引为0或顺序为第一个零的索引
  2. 右索引是数组长度-1或序列的最后一个零
  3. 你不需要实际翻转数组中的位来计算1的数量,只计算0s
  4. 你不需要从头开始重新计算这个数字,你可以调整它