这是一道老题了,可以充分让大家“抖机灵”。
输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数。
题目来源:https://www.nowcoder.com/practice/440f16e490a0404786865e99c6ad91c9?tpId=37&tags=&title=&difficulty=0&judgeStatus=0&rp=1
输入一个整数(int类型)
这个数转换成2进制后,输出1的个数
输入:5
输出:2
为什么呢?
因为,5的二进制是 101,故有两个1。
看到这道题,大部分都会想到 n%2,看到余数是否为1,其实如果你了解%2的底层原理的话,就不会再这样写了,你就会想到利用位操作。
是的,除以2 ,也是二进制数往右移一位。
代码如下:
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNextInt()){ int num = sc.nextInt(); int count = 0; while(num != 0){ if((num&1) == 1){ count++; } num = num>>1; } System.out.println(count); } sc.close(); } }
看提交结果如何:
运行速度还行,就是内存占用太多了。
那么,试想哪里还可以优化呢?
我们不妨回味下上述思路:上述右移一位,我们目的是为了得到二进制数的每一位,因为在最后一位可以通过&1 来判断是否为1.
那么,还可以怎么样得到二进制数中每一位 1 呢?
我们不妨将 num & (num-1),为什么呢?如:num = 21,二进制为10101,num-1 = 20,二进制为10100,
10101 & 10100 = 10100,恰好可以消去一个1,好,接着 num=20 , num-1= 19 ,二进制为10011;
10100 & 10011 = 10000,好家伙,又去掉一个1,这样的话,相当于是“跳级”了,什么意思呢?就是不再是老老实实地一次右移一位,你看 num & (num-1) 这样的操作可以直接跳过0 所在的位次。
故,要快得多。代码如下:
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNextInt()){ int num = sc.nextInt(); int count = 0; while(num != 0){ count++; num = (num & (num-1)); } System.out.println(count); } sc.close(); } }
提交结果如下:
内存还是占用太多,因为你还是和思路1 一样,创建了两个Int变量。
就在我一筹莫展之际,我愁到了一个高级函数,什么呢?Integer.bitCount(int num),哈哈哈,这个函数居然可以帮你直接数出二进制数中有多少个1.
哈哈哈,拿来试试:
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNextInt()){ int num = sc.nextInt(); System.out.println(Integer.bitCount(num)); } } }
提交结果:
略有改善.......毕竟少了一个count变量,哈哈哈。
Over.......