Make BITWISE AND positive

Viewed 440

I was solving one problem and it stated that we need to find the sum of all minimum number that needs to be added to the elements in the array so that the bitwise AND is greater than 0.

For eg: Given array is [4, 4, 3, 2]

then the output should be 3

(adding one to 1st 2nd and 4th element).

My approach : first I decided to find the position of the right most set in all elements and check for the overall minimum number to be added so that the and is greater than zero. But this is not working.Can anyone help in finding an alternative algo?

1 Answers

Let's solve a bit different problem first:

What minimum min number should be add to value to ensure 1 in kth position (zero based)?

We have two cases here:

if value has 1 at k position we add 0 (do nothing);

if value has 0 at k position we can add

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

Code (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)); 
  }

Demo: if we have 3 and we want 1 at 2nd position

   0b011
     ^
     we want 1 here

we should add

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

let's add: 3 + 1 == 4 == 0b100 which has 1 at 2nd position

Now we can scan all 32 positions (if integer is good old 32 bit integer int); C# code:

  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;
  }

One can improve the solution looping not for 32 positions but for the leftmost 1 of the maximum item. Here we have 4 as the maximum, which is 0b100, the leftmost 1 is in the 2 position; thus for (int i = 0; i <= 2; ++i) will be enough in the context

Simple test:

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

Outcome:

  3
Related