zoukankan      html  css  js  c++  java
  • 奇妙的位运算

    三道leetcode上的题目。

    Single Number

    Given an array of integers, every element appears twice except for one. Find that single one.

    题意即:一个数组,里面的元素每个都出现了两次,除了一个特殊的,求这个特殊元素。接触过这类题目的coder很快能够脱口而出:直接异或就ok了!因为两个相同的数异或会抵消每个bit位,结果为0.

    1 class Solution {
    2 public:
    3     int singleNumber(vector<int>& nums) {
    4         int x=0,len=nums.size();
    5         for(int i=0;i<len;i++)  x^=nums[i];
    6         return x;
    7     }
    8 };

    Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one.

    题意:这是上题的加强版,数组中每个元素都出现三次,除了一个特殊的,找出这个特殊元素。

    思路:我们也可以按位运算,计算1 bit的数量,如果每个数字都出现三次,那么每位上的1 bit数量肯定是3的倍数,相反如果不是3的倍数,那么就是那个特殊的数。但是我们可以用一个数“辅助”,因为每一位的1 bit数量统计都是类似的,所以假设正在统计某一位的1 bit数量。我们用a来表示 1 bit 的数量,当 1 bit 的数量为0时,a=0;当数量为1时,a=1;当数量为2时,a=2?非也,位运算只能表示0和1,所以这时我们引进第二个变量b,我们用b=1来代表已经有了2个 1 bit,所以当有两个 1 bit 时,a=0,b=1。数量统计结果逢3化0,所以只有0、1、2三种结果:

    bits数量    a     b
       0        0     0
       1        1     0
       2        0     1

    思路也就显而易见了,每次运算我们维护a和b的值,运算到最后即可得到结果:

     1 class Solution {
     2 public:
     3     int singleNumber(vector<int>& nums) {
     4         int a=0,b=0,len=nums.size();
     5         for(int i=0;i<len;i++){
     6             b=a&(b^nums[i]);//b由a和b异或item的对应bit与决定
     7             a=b|(a^nums[i]);//a由b和a异或item的对应bit或决定
     8         }
     9         return a;
    10     }
    11 };

    Single Number III

    Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

    For example:

    Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].

    题意:还是一个数组,每个元素出现两次,只有两个特殊的元素出现一次,把这两个特殊的元素找出来。

    思路:直接异或不得行。考虑两个特殊值,他们肯定有bit不同,想办法分开他们,再分别与其他数异或,就出来了。把所有数异或(效果等同于把两特殊数异或),取结果某个bit上的1,根据此位把数组分为两个子数组,则目的达到。

     1 class Solution {
     2 public:
     3     vector<int> singleNumber(vector<int>& nums) {
     4         int x=0,len=nums.size();
     5         for(int i=0;i<len;i++)  x^=nums[i];
     6         x=x&(-x);//取x最右边为1的bit位
     7         int r1=0,r2=0;
     8         for(int i=0;i<len;i++) (nums[i]&x)?(r1^=nums[i]):(r2^=nums[i]);
     9         vector<int> t;
    10         t.push_back(r1);
    11         t.push_back(r2);
    12         return t;
    13     }
    14 };

    参考:http://www.cnblogs.com/zichi/p/4795049.html

  • 相关阅读:
    Siri
    ArcSDE和Geodatabase10.1抢先版谍照介绍(3)——ArcToolbox工具和其他功能
    ‘马太’效应
    Linux琐屑下Resin JSP MySQL的布置和设置配备陈设2
    平安防御:分级防御对Linux服务器的攻击
    Linux无法解析域名的处理活动
    Ubuntu Linux Server的用户僻静后果分析
    大概要领确保确保Linux体系中SSH的安适性
    无错版Vsftpd Mysql Pam设置虚拟用户要领
    Redhat Linux AS4下的LAMP与Discuz装置1
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4677184.html
Copyright © 2011-2022 走看看