今日第二道题,你今天做了几道了?
在上题之前,小李子实名点赞一下牛客中剑指的题解改版,增加了牛客剑指的官方解答,看了感觉思路非常清楚,而且方法比较全,易错的点也会讲到,会不错滴~~~大大的表扬!!!
一定要坚持看完哦,最后有惊喜哦!!!
上题:
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
分析:这道题我之前看过,但是当时不会,没做对。虽然这次也不会,但是看了题解很清楚了~~
要求解1的个数,那我们要得到一个数的二进制,可以用/2取余法得到。
试试法:除二取余法(对非负数可行)
代码:
public class Solution {
public int NumberOf1(int n) {
int num=0;
while(n!=0){
int temp=n%2;
n=n/2;
if(temp==1){
num++;
}
}
return num;
}
}
当然牛客是运行不通过的,因为没有考虑负数的情况,我们考虑的都是非负情况。
所以这种方法对所有整数行不通。
方法一:转二进制字符串再比较
利用Integer.toBinaryString()函数将数转为二进制字符串,在依次与1比较
代码:
public class Solution {
public int NumberOf1(int n) {
int num=0;
String str=Integer.toBinaryString(n);
char[] char1=str.toCharArray();
for(char i:char1){
if(i=='1')num++;
}
return num;
}
}
牛客运行通过
运行时间:13ms
运行内存:9172Kb
这个方法真的还不错,哈哈哈~~
我们看点高级点的。
方法二:二进制移位法
Java中二进制移位的符号有左移>> 右移<<
我们可以设置一个二进制的1,通过移动这个1在32位中的位数,来和输入的数进行&操作。
注意一点java中的逻辑与和按位与
逻辑与:&&,是两个boolean操作
按位与:& 得到的是相同的个数,不只是1或者0;
代码:
public class Solution {
public int NumberOf1(int n) {
int num=0;
int flag=0x01;
while(flag!=0){
if((flag&n)!=0)num++;
flag<<=1;
}
return num;
}
}
牛客运行通过
运行时间:14ms
运行内存:9412Kb
这种方法其实比较好理解,但是一些细微的东西容易出错。
方法三:神奇法?!
大神还给了另外一种方法,这是我在题解中看到的解释:
/**************************************************************************************/
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
/**************************************************************************************/
代码:
public class Solution {
public int NumberOf1(int n) {
int num=0;
while(n!=0){
num++;
n=n&(n-1);
}
return num;
}
}
牛客运行通过
运行时间:17ms
运行内存:9288Kb
方法三相对于方法二,时间复杂度最坏为O(32),所以比方法二好一些,但是太难想了~~
举一反三:
(1)判断一个整数是否第2的整数次方;
举个栗子:2^1=2 10
2^2=4 100
2^3=8 1000
我们发现是否是整数次方,则该整数的二进制形式只有一个1,有转化为求解1的个数是否为1.
(2)两个整数m和n,判断m要改变几位才能变成n,其实还是二进制的问题。
1、先将两个数进行异或处理。相同为0,不同为1;
2、在求解1的个数,又转化为求1的个数。
今天写了很多,希望各位能学习到。
欢迎各位互相学习和交流哦~