问题
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:
- if V is even divide by 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:
- V = 7, which is odd: subtract 1 to obtain 6
- V = 6, which is even: divide by 2 to obtain 3
- V = 3, which is odd: subtract 1 to obtain 2
- V = 2, which is even: divide by 2 to obtain 1
- 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). xis odd if and only if the rightmost binary digit is1- subtracting 1 from
xcan be accomplished in different ways; here it would probably be most efficient by finding the position of the rightmost1inx. Call this positionp. Set the value of positionpto0and the value of all positions less thanpto1. For example,110->101(6->5 base 10.) To do this efficiently, make sure you cache the position of the rightmost1. - As kaya3 pointed out below, there is no need to subtract 1 like this. If
xis odd, then the rightmost1is guaranteed to be the rightmost digit, simply set it to0.
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