剑指offer_位运算

位运算是把数字用二进制表示以后,对每一位上0 或者1 的运算,二进制机器位运算是现代计算机科学的基础,底层技术都离不开位运算
在这里插入图片描述
二进制的位运算不是很难掌握,因为位运算总共只有5中运算:与、或、异或、 左移和右移。与 或 和 异或运算的规律我们可以用一个表总结一哈

在这里插入图片描述
左移运算符m<<n表示把m左移n位。左移n位的时候,最左边的n位将会被丢弃,同时右边补上n个0
对应10进制的数来说,左移1相当于除2,左移2相当于除以4,左移3 相当于除以8,以此类推
右移动运算符m>>n就正好相反,对应十进制的数来说,相当于*2的指数

题目10:二进制中1 的个数

题目描述:请实现一个函数,输入一个整数,输出该数二进制表示中的1 的个数,例如把9 表示成二进制是1001,有2 位是1 ,因此如果输入9,该函数输出2

思路:先判断整数二进制中最右边一位是不是1 ,接着把输入的整数右移一位,此时原来处于从右边数器的第二位移动到最右边了,再 判断是不是1。这样一次移动一位,直到整个书变成0为止

public class Numberof1 {
	public static int number1(int n) {
		int count = 0;
		while (n > 0) {
			if ((n & 1) == 1)
				count++;

			n = n >> 1;
		}
		return count;
	}

	public static void main(String[] args) {
		System.out.println(number1(1));
		System.out.println();
	}
}

这里有一个注意的点就是,右移一位和除以2在数学上是等价的,但是在效率上,右移一位比除以2要高得多,所以在实际编程中应该经可能的用移位运算符代替除法
继续深入
上面的函数如果输入一个负数,比如0X80000000,运行的时候会发生什么情况?把负数0X90000000右移一位的时候,并不是简单的把最高位的1 移到第二位变成0x40000000而是0xC00000000。 这是因为移位前是个负数,任然要保证移位后是负数,因此移位后的最高位会设置为1,如果一直做右移运算,最终这个数字就会变成0xFFFFFFF 而陷入死循环。
在这里插入图片描述
常规解法:
为了避免死循环,我们可以不右移输入的数字i:

(1)首先把i和1做与运算,判断i的最低位是不是为1。

(2)接着把1左移一位得到2,再和i做与运算,就能判断i的次低位是不是1。

(3)这样反复左移,每次都能判断i的其中一位是不是1

public static int NumberOf1Solution2(int n)
    {
        int count = 0;
        uint flag = 1;
        while (flag >= 1)
        {
            if ((n & flag) > 0)
            {
                count++;
            }

            flag = flag << 1;
        }

        return count;
    }

这个算法的缺点是效率不高,需要等到flag溢出才可以跳出循环并返回值

方法3: 高效新颖
 把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。

 public static int NumberOf1Solution3(int n)
    {
        int count = 0;

        while (n > 0)
        {
            count++;
            n = (n - 1) & n;
        }

        return count;
    }

总结:把一个整数减去1 之后再和原来的整数做位与运算,得到的结果相当于是把整数的二进制表示中的最右边一个1变成0 很多二进制的问题都可以用这个思路解决。

本章小结:
本章着重介绍应聘者在面试之前应该准备的基础知识。为了应对面试,需要从编程语言、数据结构和算法3方面做好准备
面试官通常采用概念题,代码分析题以及编程题这3种常见题型来考察影评者对某一编程语言的掌握程度。
数据结构题目一直是面试官考察的重点
数组和字符串是两种最基本的数据结构。链表应该是面试题目中频率最高的一种数据结构,如果面试官想要加大面试的难度,他有可能会选用与树(尤其是二叉树)相关的面试题。由于栈和递归调用密切相关,队列在图(包括树)的宽度优先遍历中需要用到,因此也需要掌握这两种数据结构
算法是另一个考察的重点 ,查找(特别是二分查找)和排序(快排和归并排序)是重中之重,除此以外还需要掌握时间复杂度方法,理解即使是同一思路,基于循环和递归的不同实现他们的时间复杂度依然可能大不相同。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值