简体   繁体   中英

How to determine # of 1s in any number in binary form recursively

So my method works for counting number of 1s in some odd numbers but not all and I need to determine how many 1s in a even number's binary also. This is what I have so far:

 if (n == 1){
        return count+1;
    }
    else{
        count = count + 1;
        return numOnes(n/2, count);
    }

Also can count be declared as an instance variable for recursive methods? How does it retain it's count when the method is being recursed.

The reason you are failing with even numbers (and possibly for some odd numbers) is because you don't have proper base cases for your recursion. The solution is quite simple: add another base case where n==0.

Regarding your second question - in Java, each time a method is called, the information for that method is put on the call stack. If you declare any variable inside the method, that information will be unique to each recursive call. For example, if you declare int count = 0 in your recursive method, that will create a new count variable every time the method is called. Often, programmers will not even use a local variable:

//Base cases return specific values
return recursiveCall(newParameters);

Using your problem, you could try something like:

private int numOnes(int n){
    if(n < 2){
        return n; //returns 0 for 0, and 1 for 1.
    }
    int ones = 0;
    ones += (ones % 2 == 0) ? 0 : 1;  // adds one if number is odd.
    ones += numOnes(n/2); //chops off last digit, recomputes.
    return ones;
}

The idea is that we look at each bit one at a time (by checking to see if the number is odd), then chop off that bit and look at the rest. The base case is if we only have one number left (or if all that we have left are 0's). Also note that you'll have to have special code to handle negative values (I'll leave that part up to you).

It's easy enough, but there's a small wrinkle at the minimum integer value, which we know will have 32 ones in binary as it's 2^31 represented with two's complement.

I'd suggest you drive towards the solution with some test cases first:

@Test
public void should_be_0_ones_in_zero() {
    assertEquals(0, Ones.count(0));
}

@Test
public void should_be_1_one_in_one() {
    assertEquals(1, Ones.count(1));
}

@Test
public void should_be_1_one_in_two() {
    assertEquals(1, Ones.count(2));
}

@Test
public void should_be_4_ones_in_fifteen() {
    assertEquals(4, Ones.count(15));
}

@Test
public void should_be_31_ones_in_max_integer() {
    assertEquals(31, Ones.count(Integer.MAX_VALUE));
}

Handling positive integers is pretty straightforward.

static class Ones {
    static int count(int n) {
        if (n < 2) return n;
        return (n & 1) + count(n >> 1); 
    }
} 

Here the expression:

(n & 1)

describes the one-ness of the least significant bit--ie, it's either 0 or 1. We capture that for the resulting count and then continue recursively with the remaining bits (except for the sign bit):

n >> 1

I assume you'd be interested in handling negative values also such as this one..

@Test
public void should_be_2_ones_in_negative_one() {
    assertEquals(2, Ones.count(-1));
}

and this one!

@Test
public void should_be_32_ones_in_min_integer() {
    assertEquals(32, Ones.count(Integer.MIN_VALUE));
}

At the moment, I have no better idea to handle Integer.MIN_VALUE other than to explicitly check for it.

static class Ones {
    static int count(int n) {
        if (n == Integer.MIN_VALUE) return 32;
        if (n < 0) return 1 + countForPositive(-1 * n);
        return countForPositive(n);
    }

    // expect disappointing results for negative values of n, such
    // as Math.abs(Integer.MIN_VALUE)--yes, really!
    static int countForPositive(int n) {
        if (n < 2) return n;
        return (n & 1) + countForPositive(n >> 1); 
    }
}

For negative numbers, simply add 1 to account for the sign bit. Hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM