Algorithm to reduce the binary value to zero after performing operations

我只是一个虾纸丫 提交于 2021-02-04 16:37:26

问题


I encountered this problem on an online coding platform:

String S contains the binary representation of value V and we need to calculate number of operations after which this value becomes zero. There are 2 operations to perform:

  1. if V is even divide by 2
  2. if V is odd subtract by 1

For example if S = "111", the function should return 5. Explanation: String S encodes to number V = 7. It requires five operations:

  1. V = 7, which is odd: subtract 1 to obtain 6
  2. V = 6, which is even: divide by 2 to obtain 3
  3. V = 3, which is odd: subtract 1 to obtain 2
  4. V = 2, which is even: divide by 2 to obtain 1
  5. V = 1, which is odd: subtract 1 to obtain 0

My code works perfectly fine for smaller numbers, but for insanely large numbers, I get a timeout on the coding platform and this impacts my overall score as I get zero marks for some test cases.

For example: For string S having value '1' repeated 400,000 times, the function should return 799,999

For such input values, I get a timeout error.

My code:

public class Sol3 {

    private static BigInteger bigIntegerTwo = new BigInteger("2");

    public int solution(String S) {
        BigInteger input = new BigInteger(S, 2);
        return getSteps(input, 0);
    }

    private int getSteps(BigInteger input, int counter) {
        if (input.equals(BigInteger.ZERO)) return counter;  
        counter++;
        if (input.mod(bigIntegerTwo).equals(BigInteger.ZERO)) {
            return getSteps(input.divide(bigIntegerTwo), counter);
        } else {
            return getSteps(input.subtract(BigInteger.ONE), counter);
        }
    }

    public static void main(String[] args) {
        Sol3 s = new Sol3();
        System.out.println(s.solution("011100"));
        System.out.println(s.solution("111"));
        System.out.println(s.solution("1111010101111"));
        System.out.println(s.solution("1"));
    }
}

What is the mistake in my code? Or is there a simple method using bit manipulation?


回答1:


You don't need conversion the a numeric data type. Just work with the string. The formula is:

<number of ones> + <number of digits> - <index of left most one> - 1

For instance, your solution method could be:

public static int solution(String s) {
    int firstOneAt = s.indexOf("1");
    return firstOneAt == -1 ? 0
         : s.replace("0", "").length() + s.length() - firstOneAt - 1;
}

The idea is that the division operation really is a digit-shift to the right, with the rightmost zero dropping off. It reduces the number of digits by 1. It is also the only way to reduce the number of digits. So you need as many divisions as there are digits in your input, with two exceptions:

  • We should not count pre-padded zeroes.
  • When only one significant digit is left over (a 1-digit), no division will be needed: just a subtraction will be enough.

So this means we will need to discount prepadded zeroes (or find the position of the first 1-digit) and count the number of digits from there on, and subtract one to compensate for the final operation which will not involve a division.

On top of that we need one subtraction operation for any 1-digit in the input: all 1-digits will sooner or later get shifted into the right most position at which moment a subtraction is necessary to get rid of it.




回答2:


Use the following properties about a number x represented in binary format (little endian - meaning least significant digit is rightmost) of arbitrary length (do not use a BigInteger library as it will be slow.)

  • Division by two is accomplished by right shifting one binary digit, for example 110 -> 11 (6 -> 3 in base 10).
  • x is odd if and only if the rightmost binary digit is 1
  • subtracting 1 from x can be accomplished in different ways; here it would probably be most efficient by finding the position of the rightmost 1 in x. Call this position p. Set the value of position p to 0 and the value of all positions less than p to 1. For example, 110 -> 101 (6->5 base 10.) To do this efficiently, make sure you cache the position of the rightmost 1.
  • As kaya3 pointed out below, there is no need to subtract 1 like this. If x is odd, then the rightmost 1 is guaranteed to be the rightmost digit, simply set it to 0.

Given these properties you should be able to prove an analytic formula given any input string (no manual computation necessary.)



来源:https://stackoverflow.com/questions/63459099/algorithm-to-reduce-the-binary-value-to-zero-after-performing-operations

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!