2016.5.15——leetcode:Number of 1 Bits ,

leetcode:Number of 1 Bits

代码均测试通过!

1.Number of 1 Bits

本题收获:

  1.Hamming weight:即二进制中1的个数

  2.n &= (n-1)【n = n & (n-1)】的用处

  题目:

  Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight).

  For example, the 32-bit integer ’11' has binary representation 00000000000000000000000000001011, so the function should return 3.

  notice:输入的数字是十进制,是对十进制进行判断

  思路:

  我的思路:

    遍历字符串1的个数,(疑问,数字转换成字符串的具体操作)

  leetcode/discuss思路:

    n &= n-1,将二进制n与n-1按位与,有几个1将循环几次。这种方法效率最高。

  代码1:将整型数转化为二进制数后其中的1的个数

 1 class Solution {
 2 public:
 3    int hammingWeight(uint32_t n) {
 4     int count = 0;
 5 
 6     while (n) 
 7     {
 8         n &= (n - 1);    //即为n = n&n(n-1),联想n += 1为n = n+1
 9         count++;
10     }
11 
12     return count;
13     }
14 };

  我的代码:带有main函数

 1 #include "stdafx.h"
 2 #include "iostream"
 3 #include "stdint.h"    //uint32_t的头函数
 4 using namespace std;
 5 
 6 class MyClass
 7 {
 8 public:
 9     int hanminweight(uint32_t n)
10     {
11         int count = 0;
12 
13         while(n != 0)
14         {
15             n = n & (n-1);
16             count++;
17             //cout << count << endl;测试
18             //cout << n << endl;
19         }
20         return count;
21     }
22 };
23 
24 
25 
26 int _tmain(int argc, _TCHAR* argv[])
27 {
28     MyClass solution;
29     int m;
30     uint32_t nums;
31     cin >> nums ;
32     m = solution.hanminweight(nums);
33     cout << "the number of 1bits is:" << m << endl;
34     //cin.get();    //不知道为什么cin.get()不可以了??
35     system("pause");
36     return 0;
37 }

   代码2:开始讲题意理解错了,误以为输入为二进制,现在重新写了个输入为二进制的代码。

 1 #include "stdafx.h"
 2 #include "iostream"
 3 #include <string>    //string的头文件
 4 #include "stdint.h"    //uint32_t的头函数,这里可以不用
 5 using namespace std;
 6 
 7 class Binary
 8 {
 9 public:
10     int hanminweightbinary(string s)
11     {
12         int nums = 0;
13         for (size_t i = 0; i < s.size(); i++)
14         {
15             //cout << s[i] << endl;        //测试
16             if (s[i] == '1')        //在字符串中判断时数字为整型1 应该为‘1’此为字符串,if (s[i] == 1) 出错,nums始终为0
17             {
18                 ++nums;
19             }
20             //cout << nums << endl;
21         }
22         return nums;
23     }
24 };
25 
26 int _tmain(int argc, _TCHAR* argv[])
27 {
28     Binary solution;    //若想要多次循环可以加while(true)语句
29     int m;
30     string str;
31     cin >> str;
32     m = solution.hanminweightbinary(str);
33     cout << "the number of 1bits is:" << m << endl;
34     //cin.get();    //不知道为什么cin.get()不可以了??
35     system("pause");
36     return 0;
37 }

调试过程中出错:

  错误1:error C2679: 二进制“<<”: 没有找到接受“std::string”类型的右操作数的运算符(或没有可接受的转换)

  原因:没有加string的头文件#include <string>

  错误2:nums的值始终为0

  原因:if (s[i] == 1)  应该为 if (s[i] == '1')

碎碎念(不清楚的知识点):

一。n&(n-1)作用:将n的二进制表示中的最低位为1的改为0,先看一个简单的例子:
  n = 10100(二进制),则(n-1) = 10011 ==》n&(n-1) = 10000
  可以看到原本最低位为1的那位变为0。
  弄明白了n&(n-1)的作用,那它有哪些应用?
  1). 求某一个数的二进制表示中1的个数
    while (n >0 )

      {

        count ++;
            n &= (n-1);
       }

  2). 判断一个数是否是2的方幂
  n > 0 && ((n & (n - 1)) == 0 )

  

二.to_string是将整型转换成字符串型,具体怎么用还不清楚:http://www.cplusplus.com/reference/string/to_string/可以参考这个链接

 

三.运算符

  按位与运算符(&)

    参加运算的两个数据,按二进制位进行“与”运算。

    运算规则:0&0=0;   0&1=0;    1&0=0;     1&1=1;

        即:两位同时为“1”,结果才为“1”,否则为0。

      例如:3&5  即 0000 0011 & 0000 0101 = 0000 0001   因此,3&5的值得1。

     负数按补码形式参加按位与运算。

    “与运算”的特殊用途:

      (1)清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。

      (2)取一个数中指定位

          方法:找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。

          例:设X=10101110,

              取X的低4位,用 X & 0000 1111 = 0000 1110 即可得到;

            还可用来取X的2、4、6位。

 

  按位或运算符(|)

    参加运算的两个对象,按二进制位进行“或”运算。

    运算规则:0|0=0;   0|1=1;   1|0=1;    1|1=1;

        即 :参加运算的两个对象只要有一个为1,其值为1。

        例如:3|5 即 0000 0011 | 0000 0101 = 0000 0111   因此,3|5的值得7。 

      负数按补码形式参加按位或运算。

    “或运算”特殊作用:

    (1)常用来对一个数据的某些位置1。

    方法:找到一个数,对应X要置1的位,该数的对应位为1,其余位为零。此数与X相或可使X中的某些位置1。

    例:将X=10100000的低4位置1 ,用 X | 0000 1111 = 1010 1111即可得到。

  异或运算符(^)

    参加运算的两个数据,按二进制位进行“异或”运算。

    运算规则:0^0=0;   0^1=1;   1^0=1;   1^1=0;

      即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。

    “异或运算”的特殊作用:

      (1)使特定位翻转 找一个数,对应X要翻转的各位,该数的对应位为1,其余位为零,此数与X对应位异或即可。

      例:X=10101110,使X低4位翻转,用X ^ 0000 1111 = 1010 0001即可得到。

      (2)与0相异或,保留原值 ,X ^ 0000 0000 = 1010 1110。

  取反运算符(~)

    参加运算的一个数据,按二进制位进行“取反”运算。

    运算规则:~1=0;   ~0=1;

        即:对一个二进制数按位取反,即将0变1,1变0。

    使一个数的最低位为零,可以表示为:a&~1。

      ~1的值为1111111111111110,再按“与”运算,最低位一定为0。因为“~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高。

  左移运算符(<<)

    将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。

    例:a = a << 2 将a的二进制位左移2位,右补0,

      左移1位后a = a * 2; 

    若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2

  右移运算符(>>)

    将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。

    操作数每右移一位相当于原操作数除2

     例如:a = a >> 2 将a的二进制位右移2位,

     左补0 or 补1 得看被移数是正还是负。

  无符号右移运算符(>>>)

  >> 运算符把 expression1 的所有位向右移 expression2 指定的位数。expression1 的符号位被用来填充右移后左边空出来的位。向右移出的位被丢弃。

    例如,下面的代码被求值后,temp 的值是 -4:

      -14 (即二进制的 11110010)右移两位等于 -4 (即二进制的 11111100)。

     var temp = -14 >> 2

  复合赋值运算符

  位运算符与赋值运算符结合,组成新的复合赋值运算符,它们是:

    &=    例:a &= b        相当于a=a & b

    |=    例:a |= b        相当于a=a | b

    >>=   例:a >>= b       相当于a=a >> b

    <<= 例:a <<= b       相当于a=a << b

    ^=   例:a ^= b       相当于a=a ^ b

  运算规则:和前面讲的复合赋值运算符的运算规则相似。

如果两个不同长度的数据进行位运算时,系统会将二者按右端对齐,左边补0,然后进行位运算

  

 

posted on 2016-05-15 17:42  zhuzhu2016  阅读(192)  评论(0编辑  收藏  举报

导航