剑指offer15.二进制中1的个数

看题第一思路
  • IO(input、output)分别为:I:整数(我用java语言实现,因此需要将n看作无符号整数);O:该数对应的二进制表示中1的个数。
  • Q1:从题目中例子来看,该整数是二进制还是十进制输入呢?如何甄别呢…
  • Q2:对于Java,有符号整数是如何表示的?
  • 本题是位运算tag下的题,涉及的位运算一般涉及与(&)、或(|)、非(-)、异或(^)、移位(<<、>>)运算。如何应用在本题里?
  • 思路1:可以将输入的整数转换为二进制,然后循环,逐个判断该二进制数的每一位上的数是否为1,是则count++。
思路1:
public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
		String str = Integer.toBinaryString(n);
		int count=0;
		char[] res  = str.toCharArray();
		for(int i=0;i<str.length();i++) {
			if(res[i]=='1')
				count++;
		}
		return count;		
	}
}

在这里插入图片描述

  • Integer类toBinaryString()方法,将输入转换为二进制字符串;
  • String类toCharArray()方法,将字符串转换为字符数组;
  • 遍历字符数组的每个元素,与字符1比较,以得到1的个数
  • 可以看到这种方法时间效率低
题解思路
  • 位运算:左移运算符m<<n表示将m左移n位,即将m最左边的n位丢弃,在最右边补n个0;
        右移运算符m>>n表示将m右移n位,即将m最右边的n位丢弃,在最左边补n个符号位。
  • (n&1)==1,则n的最右边一位是1,否则是0。
  • n&(n-1)会把n最右边的1变成0:若n的二进制表示中,最右边的1位于第m位;则n-1时,第m位由1变成0,而第m位之后所有0都变成1,整数中第m位之前的所有位保持不变;n&(n-1)时,相当于把它最右边的1变成0
思路2: 利用(n&1)==1
  • 可以将n逐次右移一位,和1与(&)运算;这样做的问题在于对于别的语言可能会造成死循环。
  • 可以将1做左移运算,并和n与(&)运算,以判断n的最低位、次低位…是不是1
public int hammingWeight(int n) {
		int count=0;
		while(n!=0) {
			if((n&1)==1) count++;
			n=n>>>1;			
		}
		return count;
	}

在这里插入图片描述
这里需要注意:java中右移运算符>>和无符号右移运算符>>>的区别
       java中右移运算符>>和>>>

  • 时间复杂度: l o g 2 n log_2{n} log2n(即n转换为二进制的位数)
思路3: 利用n&(n-1)
 public int hammingWeight(int n) {
		int count=0;
		while(n!=0) {
			count++;
			n = (n-1) & n;			
		}
		return count;
	}

在这里插入图片描述

  • 时间复杂度:count(即n转换为二进制后1的个数)

位运算

位运算为什么快:因为计算机内存中的数据是以0 1形式存储的,即二进制形式存储的,当进行二进制运算时无需将其转换成十进制,所以会快。

应用

与运算: 取一个数的特定位。
n&1:判断奇偶,就是取二进制的最末位(如果n的最末位是1,表示n是奇数,如果n的最末位是0,表示n是偶数)。所以结果==1,则n的最末位是1,表示n是奇数,否则为偶数。

或运算: 通常用于二进制特定位上的无条件赋值。(例如可对一个数据的某些位设置为1)。
n|1:结果就是把二进制最末位强行变成1,若要变成0,则再-1

异或运算: 定义:0和1异或0都不变,异或1则取反。即相同为0,不同为1)

  • 通常用于对二进制的特定一位进行取反操作。
  • 实现交换两个数
        a ^= b;
        b ^= a;
        a ^= b;

左移运算: a<<b代表a乘以2的b次方。

右移运算: a>>>b代表a除以2的次方b运算,通常应用于二分查找、堆的插入。
(注意算术右移和逻辑右移的区别)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值