【问题标题】:Make BITWISE AND positive使 BITWISE AND 积极
【发布时间】:2020-09-26 00:47:58
【问题描述】:

我正在解决一个问题,它指出我们需要找到需要添加到数组元素中的所有最小数字的总和,以使按位与大于 0。

例如:给定数组是 [4, 4, 3, 2]

那么输出应该是3

(将一个添加到第一个第二和第四个元素)。

我的方法:首先我决定在所有元素中找到最右边的集合的位置,并检查要添加的整体最小数量,以使 and 大于零。但这不起作用。任何人都可以帮助寻找替代算法吗?

【问题讨论】:

  • 请仅标记与问题相关的语言。如果没有相关的,因为问题是关于算法不要标记它
  • 是否允许将1添加到3d项,2添加到第4项(3),并有4 & 4 & 4 & 4 == 4?或者我们必须在示例中添加相等的数字作为1
  • @DmitryBychenko 是的,这是允许的。即使这样,结果也是 3. (1 + 2)

标签: algorithm data-structures


【解决方案1】:

让我们先解决一点不同的问题:

应将min 的最小数量添加到value 以确保1kth 位置(从零开始)?

我们这里有两种情况:

如果valuek 位置有1,我们添加0(什么都不做);

如果valuek 位置有0,我们可以添加

   min = 100...000000000 - (value & 11.....11111)
          <- k zeroes ->            <- k ones ->

代码(C#)

  private static long AddToEnsureOne(long value, int position) {
    if ((value & (1L << position)) != 0)
      return 0;

    long shift = 1L << (position);

    return shift - (value & (shift - 1)); 
  }

演示:如果我们有 3 并且我们希望 1 在第二个位置

   0b011
     ^
     we want 1 here

我们应该添加

   0b100 - (0b011 & 0b11) == 4 - 3 == 1

让我们添加:3 + 1 == 4 == 0b1001 在第二个位置

现在我们可以扫描所有 32 个位置(如果整数是好的旧 32 位整数 int); C#代码:

  private static long MinToAdd(IEnumerable<int> items) {
    long best = 0;

    for (int i = 0; i < 32; ++i) {
      long sum = 0;

      foreach (int item in items)
        sum += AddToEnsureOne(unchecked((uint)item), i); // uint - get rid of sign

      if (i == 0 || sum < best)
        best = sum;
    }

    return best;
  }

可以改进解决方案的循环不是针对32 位置,而是针对最大item 中最左边的1。这里我们以4为最大值,也就是0b100,最左边的12的位置;因此for (int i = 0; i &lt;= 2; ++i) 在上下文中就足够了

简单测试:

  Console.Write(MinToAdd(new int[] { 4, 4, 3, 2}));

结果:

  3

【讨论】:

    猜你喜欢
    • 2020-06-11
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多