1,问题描述

给定一个整数N,该整数的二进制权值定义如下:将该整数N转化成二进制表示法,其中 1 的个数即为它的二进制权值。

比如:十进制数1717 的二进制表示为:0000 0110 1011 0101 故它的二进制权值为7(二进制表示中有7个1)

 

现在要求一个比N大,且最靠近N的数,且这个数的二进制权值与N相同。(这里不考虑Integer.MAX_VALUE 和负数情形。)

对于有符号的32位整数而言:它们的补码如下:

Integer.MAX_VALUE= 0111 1111 1111 1111 1111  1111  1111 1111 (2^32-1)

Integer.MIN_VALUE=  1000 0000 0000 0000 0000 0000 0000 0000 (-2^32)

                         0 = 0000 0000 0000 0000 0000 0000 0000 0000   

                         -1= 1111 1111 1111 1111 1111 1111 1111 1111

(负数的补码是在原码的基础上,符号位不变,其余位取反,末位加1)参考:原码, 反码, 补码 详解

 

2,问题分析

思路①

先求出N的二进制权值,然后从N+1开始递增,依次判断这个数的二进制权值是否与N相同,直到找到一个相同的二进制权值的数。

而求解二进制权值的算法可以用移位操作来实现。可参考:JAVA中常用的二进制位操作

//求解正数的二进制表示法中的 1 的位数
    private static int countBit(int num){
        int count = 0;
        for(; num > 0; count++)
        {
            num &= (num - 1);
        }
        return count;
    }

 

思路①这种方式,当N很大时,效率会很慢。

那有没有更好的思路呢?

其实我们的目的是找到一个数,只要这个数的二进制权值与N相同,且该数大于N且最接近N即可。

那么,可以先将N用二进制表示出来。然后,从低位开始寻找N的二进制中出现 1 之后,第一次出现0的位,假设是第 i 位,那么将第 i 位置为1,得到一个新的数M,此时 M 的二进制中 1 的个数比N多一个。再把M的二进制中的 第 i-1 位的 1 设置为0 ,就得到了大于N且最接近N的二进制权值一样的数。

示例如下:

N= 0010 1001 0101 1111

将第5位置为0,得到了M(最右边的位为第0位)

M= 0010 1001 0111 1111

由于是从低位开始寻找第一次出现0的位。故第5位的右边全是1,再将M的 第 i-1 位(第四位)设置为0,得到了H

H= 0010 1001 0110 1111

H所对应的十进制数,就是题目中要寻找的数。

再比如:

N= 0010 1001 0101 1100

M= 0010 1001 0111 1100

H= 0010 1001 0110 1100

再比如:

N= 0000 1000

M= 0001 1000

H= 0001 0000 

 

 

3,代码实现:

 思路①实现:

 

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNextLong())
        {
            int num = sc.nextInt();
            long start = System.currentTimeMillis();
            int weight = countBit(num);
            int k = num + 1;
            while(countBit(k) != weight)
            {
                k++;
            }
            long end = System.currentTimeMillis();
            System.out.println("res:" + k + " time: " + (end - start));
        }
        sc.close();
    }
    
    
    private static int countBit(int num){
        int count = 0;
        for(; num > 0; count++)
        {
            num &= (num - 1);
        }
        return count;
    }
}
View Code

相关文章:

  • 2022-12-23
  • 2021-10-30
  • 2022-12-23
  • 2021-09-08
  • 2021-09-21
  • 2021-08-11
猜你喜欢
  • 2022-02-15
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-02
  • 2021-09-19
相关资源
相似解决方案