异或运算在算法中的经典运用

发布者:DazzlingSmile最新更新时间:2015-05-06 来源: 51hei关键字:异或运算  算法  经典运用 手机看文章 扫描二维码
随时随地手机看文章
 “一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字?”这是经典的算法题,乍看这个题的思路特别多。

   比如首先排序、然后在查找不同的数据就能找到这两个数字,这种实现方法的时间复杂度应该是在O(NlgN),因为比较排序的算法最好的时间复杂度就是这样。但是乍一看,这题就解决了,但是还没有充分运用一个条件,绝大多数元素是成对出现的,这个条件的作用是什么呢? 当然还有的思路就是hashmap实现,这种实现方法就是采用hash表存储每个变量的次数,最后遍历hash表即可,但是这种方法也存在问题,如果存在负数,或者数组元素的值特别大,采用Hashmap实现的空间复杂度太大,并不是我们需要的解决方式,hashmap适合的方式是在一定范围类的数值进行统计。上面这两种方法可能是比较快速想到的。

   这道题的实现方法很多,关键是找到最好的实现方法很难,本文就介绍采用异或运算实现这道题目的解法。

   异或运算是C语言中位运算的一种操作,这种操作对于嵌入式程序员可能比较熟悉,但是对于一般的程序员可能运用的比较少,异或操作具有如下的特征:

   0^num = num; 1^num = ~num; num ^ num = 0; 其中num = 0或者1。

   运用结合律等特征有:

   a^a^b^b^c = (a^a)^(b^b)^c=0^0^c=c;

   需要注意:如果有a + b = c; 则有可能使得a ^ b ^ c = 0;这个条件是非充分非必要,比如a = 1,b = 2, c = 3,这时候的a ^ b ^ c = 0是成立的,但是a = 2, b = 2, c = 4,则是不成立的。

   从上面的结合律可以知道如果两个相同的数进行异或操作结果是0,根据题目中元素是成对出现的,可以充分运用异或操作的结合特性,数组元素异或以后的结果肯定会包含两个不成对元素的特征。

   假设数组元素为a[N],其中N的值很大,不成对的元素为an,am。实现上述过程的步骤如下所示:

   首先,变量元素对所有元素进行异或操作,得到的结果肯定是an^am。也就说通过异或操作以后,结果中保存了an和am的特征。由于am和an不同,am^an的结果肯定是大于等于1。am和an不同,那么am^an中为1的某一个bit肯定是am或者an中某一个的特征。

   然后,定义两个值num1,num2,分别用来计算an、am,选择am^an中的某一个bit作为特征位,假设是第K位是特征位,再次对元素进行遍历,如果元素的第K位是1,这个元素可能是am或者an,那么将当前元素与num1进行异或操作,如果元素的第K为不为0,那么这个元素则可能是另一个值,那么将当前元素与num2进行异或操作。这样遍历完所有元素,因为大部分数据成对出现,根据异或运算的特征,num1,num2就分别保存了两个不同的值。

   由上面的分析可知,这种算法只需要遍历两次数组空间即可实现数据的判定,这样时间复杂度为O(N),同时因为没有hashmap之类的结构体,这样空间复杂度就是O(1)。这种算法的实现肯定是最佳的。相比前面提到的hashmap、排序算法时间复杂度和空间复杂度都要小,因此这种算法的实现应该是最佳的。

   代码实现如下:

    #include
    #include

    int whichbitone(int in)
    {
        int i = 0;
        
        while((in & (1 << i)) == 0)
            i ++ ;

        return i;
    }

    int isbitone(int in, int k)
    {
        if((in & (1 << k)) != 0)
            return 1;
        else
            return 0;
    }

    void xortest(int *array, int size)
    {
        int dxor = 0, xor = 0;
        int i = 0, j = 0;
        int num1 = 0, num2 = 0;

        for(i = 0; i < size; ++ i)
            dxor ^= array[i];
        
        if(dxor != 0)
        {
            j = whichbitone(dxor);
            for(i = 0; i < size; ++ i)
            {
                if(isbitone(array[i],j) == 1)
                    num1 ^= array[i];
                else
                    num2 ^= array[i];
            }
            /*得到第一个数*/
            printf("first data is %d ",num1);
            printf("second data is %d ",num2);
        }
    }

    int main(int argc, char *argv[])
    {
        int array[10] = {1,2,3,4,7,2,3,1,4,9};
        xortest(array,10);

        return 0;    
    }

   上面的代码基本上实现了上面的描述。

   对于本题的另一个变换“数组中元素成对出现,但是存在三个不成对的元素,如何快速的找出这三个元素?”

   这个题看起来和本题有一定的联系性,甚至我认为我们可以采用相同的方法找出三个值,但是后来发现这种方法存在一个问题,但是三个的情况要远远比两个的复杂,因为其中存在的可能性要多很多,不是不是属于这个元素就是另一个元素的问题,虽然这种解法可能导致问题产生,但是还是有可能解决的,除了当三个元素的异或结果为0,即x^y^z = 0时,这种方法是不成立的。
   对于三个不同元素的找份,我认为主要是找到其中的一个元素,然后将这个元素移除,在进行上述的另外两个元素寻找。当然我们首先排除三个数据异或为零的特殊情况。具体的实现可以参考http://blog.csdn.net/zzran/article/details/8108787

   还是存在这个问题,如果这三个元素异或以后的值刚好为零,这种方法不能解决了,因此采用异或解决只有一个不成对或者两个不同元素的问题是没有问题的,对于三个元素具有一定的可行性,但是不一定时时成立。

   异或运算在算法中针对的问题也是特定的,主要是这种元素成对出现的问题,如果不成对出现,这种算法的实用性能会大大的降低,即使是重复元素都不一定是实用的。

关键字:异或运算  算法  经典运用 引用地址:异或运算在算法中的经典运用

上一篇:散列的C语言实现
下一篇:C/C++中宏定义的经典运用

推荐阅读最新更新时间:2024-03-16 14:00

单片机ADC采样算法----有效值采样法
在使用单片机ADC功能采样数据时,通常情况下用平均值计算就够了,但是在计算功率时就需要用有效值来计算真正做功的情况。如果是标准的正弦波的话,正弦波的峰值是有效值得1.414倍,可以通过峰值来计算有效值。但是实际应用中波形往往会发生畸变,如果按照1.414这个比例计算的话,误差往往会比较大。所以必须通过计算正弦波的面积来求有效值。 有效值又叫均方根值,对数据的平方和取平均再开方所计算出来的值。所以通常情况下采用的计算方法是:将所有值平方求和,求其均值,再开平方,就得到均方根值。用公式表达的话就是这样。 下面就通过C代码来实现这个公式: //取均方根值 u16 get_rms1( void ) { static u16
[单片机]
单片机ADC采样<font color='red'>算法</font>----有效值采样法
一种用于永磁同步电机电流测量误差校正的自适应选择性谐波消除算法
一、文章摘要 在电流传感器中,测量误差是不可避免的,这会导致速度波动,包括定子的一倍和两倍电气频率。对于不期望的谐波,自适应选择谐波消除(ASHE)算法输出和正弦信号乘以自适应权重。在里面为了解决当前测量误差(CME)问题文章采用了ASHE算法。根据确定性表面安装永磁体的功能关系同步电机(SPMSM),所采用的算法提取稳态速度误差的谐波,并输出q轴电流补偿。 但是,没有明确的联系速度和d轴电流之间的关系,因此它们之间的关系是不确定的。剩余的d轴CME导致较差的电流性能。因此本文提出了一种改进的ASHE算法,其同时补偿dq轴CME,取决于它们的相互确定性连接。所提出的方法确实不需要电机参数、额外的传感器或复杂的计算过程。最后,验
[嵌入式]
一种用于永磁同步电机电流测量误差校正的自适应选择性谐波消除<font color='red'>算法</font>
华中科技大学吕志鹏团队获EDA国际算法竞赛冠军
在11月4日结束的EDA(电子设计自动化)领域的国际会议ICCAD 2021(计算机辅助设计国际会议)上,华中科技大学计算机学院吕志鹏教授团队获得了CAD Contest布局布线算法竞赛的第一名,今年是该团队首次参加ICCAD竞赛,团队成员还包括苏宙行博士、研究生罗灿辉、梁镜湖和谢振轩,平均年龄仅24岁。 EDA是电子设计的基石产业,是芯片设计的根基。ICCAD会议始于1980年,是EDA领域历史最悠久的顶级学术会议之一,其中CAD Contest算法竞赛作为会议的标志性事件,长期以来受到国际学术界与工业界的广泛关注。每届竞赛的赛题均来自 Cadence、Synopsys、Mentor Graphics、Nvidia、IBM等
[手机便携]
华中科技大学吕志鹏团队获EDA国际<font color='red'>算法</font>竞赛冠军
【51单片机快速入门指南】4.3.4: MPU6050使用Madgwick AHRS算法实现六轴姿态融合获取四元数、
STC89C516 32MHz Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 上位机:Vofa+ 1.3.10 移植自AHRS —— LOXO,算法作者:SOH Madgwick 源码 为了避免所用RAM超标,部分变量设为idata类型,移植时需注意。 所用MCU为STC89C516 晶振16MHz 6T模式 stdint.h见【51单片机快速入门指南】1:基础知识和工程创建 软件I2C程序见【51单片机快速入门指南】4: 软件 I2C 串口部分见【51单片机快速入门指南】3.3:USART 串口通
[单片机]
【51单片机快速入门指南】4.3.4: MPU6050使用Madgwick AHRS<font color='red'>算法</font>实现六轴姿态融合获取四元数、
单片机汇编语言实现DES加密算法
目前在金融界及非金融界的保密通信中,越来越多地用到了DES算法。DES(Data Encryption Standard)即数据加密算法,是IBM公司于 1977年研究成功并公开发表的。随着我国三金工程尤其是金卡工程的启动,DES算法在POS、ATM、磁卡及智能卡(IC卡)中被广泛应用,以此来实现关键数据的保密。如信用卡持卡人的PIN的加密传输、IC卡与POS间的双向认证、金融交易中的密码键盘等,均用到DES算法。由于密码键盘不可能使用高级语言,所以用汇编语言实现DES就非常实用。 1 DES算法的简单原理 DES是一种分组密码。假定明文m是由0和1组成的长度为64位的符号串,密钥k也是64位的0、1符号串。 设
[单片机]
浅析基于ARM的单电源心电图检测的原理及算法实现
随着心电图技术的临床应用和电子技术的发展,心电图作为生物医学测量中一项较成熟、应用较广泛的技术,已逐渐成为一种常规临床检查的手段,并在心脏疾病的诊断、监护以及药效分析等方面发挥着十分重要的作用。 目前常用的心电检测电路多为双电源供电,这种方案需要很多的电源器件和较大面积的布局布线,而这些都将增加产品的成本。 本文给出的设计采用单电源供电,可以解决上述问题并降低产品成本,同时该设计还在基于ARM核的嵌入式系统中采用了简单实用的算法,能快速准确定位QRS复波(即计算人的心率)。该设计面向广大家庭用户而设计,体积较小,只需要一台个人电脑与之连接,便可实时地操作、观测心电信号。 心电信号采集系统的基本架构如图1所示。人体的心电信号经
[单片机]
浅析基于ARM的单电源心电图检测的原理及<font color='red'>算法</font>实现
6种常见的单片机数字滤波算法
单片机主要作用是控制外围的器件,并实现一定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是介绍如何用单片机实现数字滤波。 在单片机进行数据采集时,会遇到数据的随机误差,随机误差是由随机干扰引起的,其特点是在相同条件下测量同一量时,其大小和符号会现无规则的变化而无法预测,但多次测量的结果符合统计规律。为克服随机干扰引起的误差,硬件上可采用滤波技术,软件上可采用软件算法实现数字滤波。滤波算法往往是系统测控算法的一个重要组成部分,实时性很强。 采用数字滤波算法克服随机干扰的误差具有以下优点 1、数字滤波无需其他的硬件成本,只用一个计算过程,可靠性高,不存在阻
[单片机]
市场常见的自动驾驶算法对比
目前,学术圈还是用“打榜”来对自动驾驶算法评分。所谓“打榜”就是在某一数据集上利用其训练数据集来测试算法的优劣,目前自动驾驶圈内最常用的打榜数据集是安波福Aptiv旗下的nuScenes。严格意义上的自动驾驶算法评分对比几乎是不可能的,单独对比算法不够公允,此外还必须考虑算法的效率和落地可行性。训练数据集的数据结构也会影响算法的发挥。同时由于深度学习的不可解释性,在nuScenes数据集上表现好不代表在其他数据集也会表现好,也许会表现得很差,同样道理在nuScenes数据集上表现不好不代表在其他数据集也表现不好。当然算力大小无关算法的准确度。 nuScenes数据集的任务包括六大类,分别是3D目标检测detection、目标追
[嵌入式]
市场常见的自动驾驶<font color='red'>算法</font>对比
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved