Dealing with padding when using `Integer.toBinaryString()` in Java - java

I want to implement Method2 for this problem http://www.geeksforgeeks.org/find-two-non-repeating-elements-in-an-array-of-repeating-elements/ but I have one issue. I dont know how have to divide the numbers from the array in two groups (ones that have '1' at specified position in their binary representation, and ones that dont have) I thought that I have to use Integer.toBinaryString() for each number in the array with the following method:
private static boolean hasOne(int number, int i) {
String s = Integer.toBinaryString(number);
if(s.charAt(i) == '1')
return true;
return false;
}
But the problem is that not every numbers have the same length in their binary representations and the method doesnt work correctly. How can I handle this? I.e. how can I deal with the padding?

It's actually very close to what you've got. Let's say you're checking for a binary value at position 6. That would be..
0101011
------^
Easiest thing to do is, before you check if the value is 1 or 0, just check that the size of the binary string is larger than the index.
if(s.length() <= i) {
return false;
}

Since you're having trouble taking the extra step of explicitly converting to binary and finding the set bit there, just know that the provided code ports simply to java, since it's mainly bitwise operations:
public static void main (String[] args)
{
int arr[] = {2, 3, 7, 9, 11, 2, 3, 11};
int xor = 0;
for (int i = 0; i < arr.length; i++) {
xor ^= arr[i];
}
int set_bit_no = xor & ~(xor-1);
int x = 0, y = 0;
for (int i = 0; i < arr.length; i++) {
if ((arr[i] & set_bit_no) != 0) {
x ^= arr[i];
} else {
y ^= arr[i];
}
}
System.out.println(x); // prints 7
System.out.println(y); // prints 9
}

First off, you can pad your binary string with a combination of String.format and replace:
String s = String.format("%32s", Integer.toBinaryString(number)).replace(' ', '0');
You can also use bitwise operators in order to determine whether a given number's binary representation has a 1 in a certain spot.
For example, consider the decimal number x = 20, which is 10100 in binary. Further suppose that you want to determine whether the binary number has a 1 in the third spot from the right n = 3. You can use bit shifting >> to shift the binary sequence to the right two times n - 1, and then mask & it with 1.
The resulting expression will look like (20 >> 2) & 1, and will evaluate to one if there is indeed a 1 in the third spot from the right, or a zero if it doesn't. In this case, it evaluates to 1.
So you can further generalize this to:
private static boolean hasOne(int number, int i) {
return ((number >> (i - 1)) & 1) == 1;
}
You can learn more about bitwise and bitshift operators in the Java Tutorials.

Related

Find repeating bit sequence in number

How can I find multiples of a given bit sequence?
So the code should work like this:
int bit = 0b100
for (int i = 0; i<=50;i++){
if (bit in i){
print(i);
}
}
This should print 4 (100) and 36 (100100).
I was trying to iterate through it and bit-mask it but it also printed numbers like 40 (101000).
So it should only print numbers containing only multiplies of that sequence (100, 100100, 100100100 ...) but not numbers like 1100, 1001001 ...
You can use the modulo operator and shift operator to check the lower bits of the number and "reduce" the incoming number to check the next lower bits of the remaining number. The algorithm works like this:
Do a modulo of the sequence on the number to check. The modulo must be 0.
So when you have the sequence 0b100 and you have a number to check like 0bXXXXXXXX101 the modulo would be 0b001, which is not 0 and you know the number can't be a sequence of multiple 0b100s.
Shift the remaining number to the right, since you have already checked the first N bits on the right.
You shift the number with the >> operator. This will move the bits to the right, dropping the already checked bits:
0bXXXXXXXX101
0bXXXXXXXX (shifted to the right)
The tricky part is to calculate how big the shift is. You can use log2() to figure that out. When you completed the shift, you go back to point 1 above.
The complete code can look like this:
public static boolean isMultipleOfSequence(int sequence, int number) {
if (sequence == 0) {
return number == 0;
}
while (number != 0) {
int remaining = number % sequence;
if (remaining != 0) {
return false;
}
int shift = log2(sequence);
number = number >> shift;
}
return true;
}
public static int log2(int value) {
return Integer.SIZE-Integer.numberOfLeadingZeros(value);
}
When you try it with the following code:
System.out.println(isMultipleOfSequence(0b100, 0b100));
System.out.println(isMultipleOfSequence(0b100, 0b100100));
System.out.println(isMultipleOfSequence(0b100, 0b100100100));
System.out.println(isMultipleOfSequence(0b100, 0b101100100));
System.out.println(isMultipleOfSequence(0b100, 0b100110100));
System.out.println(isMultipleOfSequence(0b101, 0b101101101));
System.out.println(isMultipleOfSequence(0b101, 0b100101101));
You will get the following output:
true
true
true
false
false
true
false
You might need to check for negative inputs as this method only works for positive numbers.
I'm not sure how to do it with pure math, but regex works:
Pattern pattern = Pattern.compile("^(100)+$");
for (int i = 0; i < 100; i++) {
String binary = Integer.toBinaryString(i);
if (pattern.matcher(binary).find()) {
System.out.println(i + " " + binary);
}
}
Edit: What about going the other direction?
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 10; i++) {
builder.append("100");
System.out.println(Integer.parseInt(builder.toString(), 2));
}

Plus one leetcode

I am doing a question on leetcode, 66. Plus One.
You are given a large integer represented as integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading 0's.
Increment the large integer by one and return the resulting array of digits.
Example 1
Input: digits = [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Incrementing by one gives 123 + 1 = 124.
Thus, the result should be [1,2,4].
My solution is:
class Solution {
public int[] plusOne(int[] digits) {
int num = 0;
for (int a : digits) {
num = 10*num + a;
}
int n=num+1;
String str=String.valueOf(n);
int arr[]=new int[str.length()];
for(int i=0;i<str.length();i++){
arr[i]=str.charAt(i)-'0';
}
return arr;
}
}
I am getting many test cases failed, one being:
Input:
[9,8,7,6,5,4,3,2,1,0]
Output:
[1,2,8,6,6,0,8,6,1,9]
Expected:
[9,8,7,6,5,4,3,2,1,1]
Can anyone help me with it?
Think before you leap. And consider the edges.
Why would they do the seemingly idiotic move of storing an number, digit by digit, in an int array? Makes no sense, right?
Except... computers aren't magic. int can't represent any number. A computer's storage is not infinite. Specifically, an int covers 32 bits (4 bytes), and thus can only represent at most 2^32 different numbers. int 'uses' its alloted space of 2^32 by dividing it evenly amongst positive and negative numbers, but negative numbers get one more (because the '0' is in the positive space). In other words, all numbers from -2^31 to +2^31-1, inclusive.
9876543210 is larger than that.
You're trying to turn that array of digits into an int and that is a dead end. Once you do that, you get wrong answers and there is no fixing this. your algorithm is wrong. You can figure this stuff out, and you should always do that with leetcode-style problems, by first carefully reading the assignment. The assignment covers the limits. It says how large these arrays can be, and I'm sure it says that they can be quite large; large enough that the number inside it is larger than 2^31-1. Probably larger than 2^63-1 (which a long can reach).
Then you know the algorithm you need to write can't involve 'turn it into an int first'. That's usually the point (many problems are trivial if small, but become interesting once you make things large).
The algorithm they want you to write must not involve any conversion whatsoever. Increment the array in place. This isn't hard (just think about it: without converting anything, how do you turn [1, 2, 3] into [1, 2, 4]? That should be simple. Then think about how to deal with [1, 9, 9]. Finally, think about how to deal with [9, 9, 9]. Then you've covered all the cases and you have your answer.
In continuation to the detailed explanation of rzwitserloot, in case you are interested in code for the problem.
class Solution {
public int[] plusOne(int[] digits) {
int size = digits.length;
int i=0;
for(i = size-1 ; i >= 0 ; i--){
if (digits[i] != 9) {
digits[i] += 1;
break;
} else {
digits[i] = 0;
}
}
if(i == -1) {
int[] newDigits = new int[size+1];
newDigits[0] = 1;
return newDigits;
}
return digits;
}
}
This is a pretty trivial task, but in some test cases the value is too high to represent even as long, so the best candidate is BigInteger.
public int[] plusOne(int[] digits) {
BigInteger val = BigInteger.ZERO;
for (int i = 0; i < digits.length; i++)
val = val.multiply(BigInteger.TEN).add(BigInteger.valueOf(digits[i]));
val = val.add(BigInteger.ONE);
String str = val.toString();
digits = str.length() == digits.length ? digits : new int[str.length()];
for (int i = 0; i < digits.length; i++)
digits[i] = str.charAt(i) - '0';
return digits;
}
P.S. Sure, you can do this without BigInteger.
public int[] plusOne(int[] digits) {
boolean carry = true;
for (int i = digits.length - 1; carry && i >= 0; i--) {
carry = digits[i] == 9;
digits[i] = carry ? 0 : digits[i] + 1;
}
if (carry) {
int[] tmp = new int[digits.length + 1];
tmp[0] = 1;
System.arraycopy(digits, 0, tmp, 1, digits.length);
digits = tmp;
}
return digits;
}
Think about a mileage counter in a car. How does it work?
Whenever a 9 turns around, it turns the number left to it too.
So for incrementing by one, you'd start from the right, increment by one and if you incremented it to a 10, set it to a 0 instead and continue with the next digit to the left. If you reached the leftmost digit and still didnt finish, add a 1 to the left and set everything else to 0.
Example:
8
9 <- incremented rightmost
10 <- 9 turned to a 10, leftmost digit reached, add a 1 to the left and set everything else to 0
...
18
19 <- incremented rightmost
20 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
108
109 <- incremented rightmost
110 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
998
999 <- incremented rightmost
1000 <- 9 turned to a 10, set to 0 instead, increment the next one to the left, turned to a 10 too, set to 0 instead, ...
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Scratch {
public static void main(String[] args) {
int[] digits = new int[0];
for (int i = 0; i < 100; i++) {
digits = plusOne(digits);
System.out.println(IntStream.of(digits).mapToObj(Integer::toString).collect(Collectors.joining()));
}
}
public static int[] plusOne(int[] digits) {
boolean finished = false;
for (int i = digits.length - 1; !finished && i >= 0; i--) {
if (++digits[i] % 10 == 0) {
digits[i] = 0;
} else {
finished = true;
}
}
if (!finished) {
// not finished after exiting the loop: every digit was turned from a 9 to a 10 -> we need one digit more
// initialize a new array with a length of 1 more digit, set the leftmost (index 0) to 1 (everything else is 0 by default)
digits = new int[digits.length + 1];
digits[0] = 1;
}
return digits;
}
}
plus one in leetcode solve on dart language
class Solution {
List<int> plusOne(List<int> digits) {
for(int i=digits.length - 1; i>=0; i--){
if(digits[i] < 9){
++digits[i];
return digits;
}
digits[i]=0;
}
List<int> ans = List.filled(digits.length+1, 0);
ans[0]=1;
return ans;
}
}
Here is my solution:
Runtime: 0 ms, faster than 100.00% of Java online submissions for Plus One.
Memory Usage: 40.8 MB, less than 92.31% of Java online submissions for Plus One. for Plus One.
public int[] plusOne(int[] digits) {
for(int i=digits.length-1;i>=0;i--) {
if(digits[i]<9) {
digits[i]=digits[i]+1;
return digits;
}else {
digits[i]=0;
if(i==0) {
digits= new int[digits.length+1];
digits[0]=1;
}
}
}
return digits;
}
My solution:
Runtime: 0 ms, Memory Usage: 2.1 MB,
play.golang link: https://go.dev/play/p/Vm28BdaIi2x
// function to add one digit based on diff scenarios
func plusOne(digits []int) []int {
i := len(digits) - 1
// while the index is valid and the value at [i] ==
// 9 set it as 0 and move index to previous value
for i >= 0 && digits[i] == 9 {
digits[i] = 0
i--
}
if i < 0 {
//leveraging golang's simplicity with append internal method for array
return append([]int{1}, digits...)
} else {
digits[i]++
}
return digits
}

To reach the target number from 0 in minimum number of steps

Problem Statement:
Find the minimum number of steps required to reach a target number x from 0 (zero), using only two operations: +1 (add 1 to the number) or *2 (multiply 2 with the number).
So here's the Logic that I came up with:
The best way is to work backwards. Start from the number you need:
Subtract 1 if the number is odd.
Divide by 2 if the number if even.
Stop when you get to zero.
For example, for 29, you get 28, 14, 7, 6, 3, 2, 1, 0.
And, here's what I have tried doing (Java 7):
kValues is an array that has the x values for which the steps are needed to be computed and stored in an array called result.
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,x,i,steps;
int result[] = new int[size];
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = (int)kValues[i]; x != 0 ; ++steps)
{
if((x % 2) == 0)
x /= 2;
else x--;
}
result[i] = steps;
}
return result;
}
My Problem:
This is a Hackerrank question and I am supposed to write an efficient code. I was successful with 7/11 test cases and others were timed out. Since, it is a Hackerrank question, I can't change the function definition or the return type. That is the reason why I am converting from long to int in my for loop, in order to use % (modulus). I would like to know where I am going wrong. Is my algorithm taking too long to compute (for the number of values close to a million)? Which is obviously the case, but how do I alter my algorithm in order to pass all the test cases?
Thank you in advance :)
for (x = (int)kValues[i]; x != 0 ; ++steps)
The fact that you are casting a long to an int is very suspicious. You might get a negative number when you do that.
Say x == -2: you divide it by 2 to give -1, then subtract 1 to give -2. You'll keep doing that indefinitely.
Just define x to be a long, and remove the cast.
So, here's the working code. I had forgotten to append L while using the modulo. Silly mistake led to so much of typing. LOL!!
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,i,steps;
int result[] = new int[size];
long x;
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = kValues[i]; x != 0 ; ++steps)
{
if((x % 2L) == 0)
x /= 2L;
else x -= 1L;
}
result[i] = steps;
}
return result;
}
Here is a very short version, using bit-analysis:
static int[] countOperationsToK(long... input) {
int result[] = new int[input.length];
for (int i = 0; i < input.length; i++)
if (input[i] > 0)
result[i] = Long.bitCount(input[i]) + 63 - Long.numberOfLeadingZeros(input[i]);
return result;
}
The idea here is to look at the binary number, e.g. for 29 that is 11101. There are 4 bits set, so we'd need to do +1 four times, and the highest bit position is 4, so we need to left-shift (i.e. *2) four times, for a total of 8 operations: +1, *2, +1, *2, +1, *2, *2, +1.
numberOfBits = Long.bitCount(x)
highBitNumber = floor(log2(x)) = 63 - Long.numberOfLeadingZeros(x)
The highBitNumber part doesn't work if value is zero, hence the if statement.
For input number x,
Minimum no. of Ops = (int)log2(x) + Long.BitCount(x)

Big negative integer representation in a LinkedList

My LinkedList represents big numbers by having one digit in each of the nodes.
I can represent positive big integers in a LinkedList with this code:
public BigInteger(int x)
{
list = new LinkedList<Integer>();
while (x > 0)
{
list.push(( x % 10 ));
x = x / 10;
}
}
Declaring:
BigInteger bigPositive = new BigInteger(91234)
Produces:
[9,1,2,3,4]
However, I am not sure how to represent big negative integers such as -9321312345
You could push a 1 or a 0 to the front of the list, indicating whether it was positive or negative. For instance:
(15) would map to [1 1 5]
(-13) would map to [0 1 3]
(1) would map to [1 1]
And so on. You'd just have to know to interpret that first number as a sign (+/-), and not part of the value.
If BigInteger is your own custom class, you could add a Boolean property that determines whether the integer is positive or negative.
Then, in your constructor, you could determine the sign of the integer and set that property accordingly.
public BigInteger(int x) this value for int x the input itself would be the limit so you can never go over.
Why not just have ?
public BigInteger(int x){
bigIntValue = x;
}
Because that's not the point. You want to be able to create values bigger then the intended int from the input.
The better option IMO would be something along the lines of add a String as the input then having an operation that can push int's or something you want into the back or front of the linklist.
public BigInteger(String x)
{
int endLoop = 0;
list = new LinkedList<char>();
// have a boolean for negative in your class then multiple by
// negative one to your operations if its true.
if(x.charAt(0) == '-'){
this.negative = true;
endLoop = 1;
}
list = new LinkedList<char>();
int i = x.length() - 1;
while(i >= endLoop) {
if(!validNumber(x.charAt(i)) //fail
list.push(( x.charAt(i)));
i--;
}
}
// this checks if it's a number.
boolean validNumber(char n){
for(int i = 48; i =< 57; i++){
if(n = i) return true;
}
return false;
}
You can even change the type of your lists to int if you want by writing a converter from char to int.
You could do the same they do in binary; by having the firstmost digit determine the sign
0b0100 == 4
0b1100 == -4
Similarly you could write
{0, 1, 1} == 11
{1, 1, 1} == -11,
Although this deviates from the initial idea; since you ARE working with integers, you could do this:
{-1, 1} == -11
{ 1, 1} == 11

Reverse bits in number

For example, I have the binary number 1011 which is equal to decimal 11. I want the reverse bit's location such that it become 1101, which is decimal 13. Here is code:
import java.util.*;
public class bits {
public static void main(String[] args) {
Scanner scnr=new Scanner(System.in);
System.out.println("enter x:");
int x=scnr.nextInt();
int b=0;
while (x!=0){
b|=( x &1);
x>>=1;
b<<=1;
}
System.out.println(b);
}
}
But when I enter x 11 then it prints 26. What is the mistake?
You are shifting b one time too many. Do the shift first (so that the first time, when b == 0, it has no effect):
while (x!=0){
b<<=1;
b|=( x &1);
x>>=1;
}
Slightly offtopic. There's also the option of the built-in bit reversing features of Java.
See http://java.sun.com/javase/6/docs/api/java/lang/Integer.html#reverse(int)
EDIT: This assumes you're using Java 1.5 or newer.
Use >>>= instead of >>=
If you want to change method signature to public static byte reverse(byte in) this will not work on negative values because there is implicit cast to int.
The program do not work for input like 1, 2
int reverseBits(int x)
{
int b = 0;
while (x != 0)
{
b <<= 1;
b |= ( x & 1);
x >>= 1
}
return b;
}
input 1 output 1, should be 8 right?
input 2 output 1, should be 4.
Note for beginners: I use hexadecimal (0-9 and A-F) because one hexadecimal digit maps to 4 binary bits perfectly. Instead of writing 1010, I use A (10 decimal). You can tell Java to use hexadecimal (literals) by starting with 0x as in 0x0A.
As stated before, 1 should output 8 (0001 to 1000).
So instead of while(x!=0), the code needs to shift the first bit as far as the length of the bits needed in this example it is 4.
for (int i = 0; i < 4; ++i) { // not while (x!=0){
b<<=1;
b|=( x &1);
x>>=1;
}
Hex convert 0-F: 0=0 1=8 2=4 3=C 4=2 5=A 6=6 7=E 8=1 9=9 A=5 B=D C=3 D=B E=7 F=F
Or full 8 bit example:
public static byte reverse(byte x) {
byte b = 0;
for (int i = 0; i < 8; ++i) {
b<<=1;
b|=( x &1);
x>>=1;
}
return b;
}
public static void main(String args[]) {
byte[] nums = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
(byte) 0xAA, (byte) 0xFE, (byte) 0xFF };
for (byte b : nums) {
System.out.printf("%02X=%02X ", b, reverse(b));
}
System.out.println();
}
Output:
00=00 01=80 02=40 03=C0 04=20 05=A0 06=60 07=E0 08=10
09=90 0A=50 0B=D0 0C=30 0D=B0 0E=70 0F=F0 10=08 11=88 AA=55 FE=7F FF=FF
b is shifted left once too often. I expect input 1 to result in output 2. Move the Shift two lines up.
you shifted b once too many. try shifting b to the left before doing the |=:
while (x!=0){
b<<=1;
b|=( x &1);
x>>=1;
}
System.out.println(b);
You're left shifting b one time more than required. Add b >>= 1 after your while loop.
while(x!=0){
b<<=1;
b|=(x&1);
x>>=1;
}
The result is twice as much as expected so the last left shift operation (one left shift doubles the value) is too much.
It is safe to use the unsigned right shift operator (>>>) in the while loop to obviate the danger of running into an infinite loop for -ve numbers.
while (x!=0){
b<<=1;
b|=( x &1);
x>>>=1;
}
My new java code reverse bits in an integer using java with powerful bit manipulation. It is working with positive, negative and zero values. Hope it helps.
public static int reverseDigits(int num) throws Exception {
if (num == 0) {
return Integer.MAX_VALUE | Integer.MIN_VALUE;
}
int count = Integer.SIZE * 8 - 1;
int reversed = num;
boolean positive = true;
if (num < 0) {
positive = false;
}
if (positive) num >>= 1;
while(num != 0) {
reversed <<= 1;
reversed |= (num & 1);
num >>>= 1;
count--;
}
if (positive) reversed <<= count;
return reversed;
}
You can represent bits in integer with my other bit manipulation code in java what print zeroes on the left:
https://stackoverflow.com/a/39056535/6738542
Because Integer.toBinaryString() will hide the zeroes on the left.
Metal |,,|
// i/p=3
// o/p=3221225472
// Clearly observe the 1L while doing the left shift, if ignored it will fail to return the expected output dur to mismatch in bit size.
public static long reverse(long n) {
long rev = 0;
for(int i = 31; i >=0; i--){
if((n & 1<<i) != 0){
rev = rev | 1L<<(31-i);
}
}
return rev;
}

Categories