如何以递归方式以二进制形式确定任意数字的1

时间:2015-02-02 23:00:26

标签: java recursion methods count binary

所以我的方法适用于计算一些奇数但不是全部的1的数量,我需要确定偶数个二进制数中有多少1。这就是我到目前为止所做的:

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

还可以将count声明为递归方法的实例变量吗?当递归方法时,它如何保持计数。

2 个答案:

答案 0 :(得分:2)

你使用偶数(以及可能是某些奇数)失败的原因是因为你的递归没有适当的基本情况。解决方案非常简单:添加另一个基本情况,其中n == 0。

关于你的第二个问题 - 在Java中,每次调用一个方法时,该方法的信息都放在调用堆栈上。如果在方法中声明 中的任何变量,则该信息对于每个递归调用都是唯一的。例如,如果在递归方法中声明int count = 0,则每次调用该方法时都会创建一个新的count变量。通常,程序员甚至不会使用局部变量:

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

使用您的问题,您可以尝试类似:

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

我们的想法是,我们一次查看每个位(通过检查数字是否为奇数),然后切断该位并查看其余位。基本情况是,如果我们只剩下一个数字(或者我们剩下的所有数字都是0)。另请注意,您必须使用特殊代码来处理负值(我会将该部分留给您)。

答案 1 :(得分:0)

这很容易,但是在最小整数值处有一个小皱纹,我们知道它将有二十二个二进制,因为它的2 ^ 31表示为两个&#39; s补。

我建议您首先使用一些测试用例来解决问题:

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

处理正整数非常简单。

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

这里的表达式为:

  

(n&amp; 1)

描述最低有效位的一个 - 即,它是0或1.我们捕获结果计数,然后继续递归剩余的位(符号位除外):

  

n&gt;&gt; 1

我认为你也有兴趣处理负值,例如这个......

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

和这一个!

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

目前,除了明确检查之外,我没有更好的办法处理Integer.MIN_VALUE。

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

对于负数,只需添加1即可考虑符号位。希望它有所帮助!