zoukankan      html  css  js  c++  java
  • 不借助第三个变量交换a,b两个变量值

    从一个面试题说起...

    不借助第三个变量交换a,b两个变量值

    一个很经典的答案是通过异或来解决

    
    a=a^b;
    b=a^b;
    a=a^b;
    
    

    关键字

    
    [
        "异或",
        "逻辑运算符",
        "乔治·布尔",
        "香农"
    ]
    
    

    先决条件

    0为假,1为真

        插曲>>>如果读到"0为假,1为真",心底肯定略过了,这谁都知道的啊...
    但是如果是写出来,但是找不到出处.即使常识也不太肯定了...
    
    

    "^":对应逻辑运算异或(XOR)。
    重点在"异",只有[1]XOR[0]或[0]XOR[1]才为1;一真一假即真;

    a ^ a = 0 ;
    a ^ 0 = a ;

    先决条件.出处和推导

    0为假,1为真

    香农已经知道,数学上有一种逻辑代数系统,叫做布尔逻辑,它得名于英国数学家乔治·布尔(George Boole)。在布尔逻辑中,任何逻辑表达式的计算结果都不是数值,而是“真”、“假”这两种真值。你只需要使用逻辑运算符“与”、“或”、“非”,就可以表达任何你想表达的逻辑语句。

    在逻辑中,真值或逻辑值是指示一个陈述在什么程度上是真的。在计算机编程上多称作布尔值。在经典逻辑中,唯一可能的真值是真和假。但在其他逻辑中其他真值也是可能的。

    强行补充一波,如果你非要想让"1为假,0为真",请搜索:"负逻辑".
    关于真假由来,我只能找这么多了...

    a ^ a = 0 ;a ^ 0 = a ;

    二进制的运算

    
        0110
    ^  0000
    ------------
    =  0110
    
    

    再来谈下两个变量的交换.

    其实虽然变量值还是[a,b]
    但是值可能会出现3个的.

    举个栗子↓

    a的值 b的值 出现的值
    0 0 [0]
    0 1 [0,1]
    9 5 [9,5,12]
    ... ... ...

    第一步a=a^b;此时,相当于将a和b绑定一下关系.
    只有两个变量,没有第三者插足,要交换两个变量的值,不绑定关系,不可能凭空交换吧...

    数据库角度考虑的话,类似,表A和表B本来是没有关系的,
    但是又想交换两个表之间的数据,还不允许有第三张表的出现,
    这个时候,更改了表A的结构.增加了一列.(插入这段话,希望不会让不懂的人更晕了...)

    从关系角度来看:

    1.建立关系a,此时的a已经变了...
    2.根据关系,给b赋值为a,b←a,工作完成了50%
    3.根据关系,给a赋值为b,a←b.

    从更改状态来看:

    1.a进化为a(状态1);b保持原状态;
    2.b进化成最终状态b(状态1),即:a;
    3.a再次进化成最终状态a(状态2),即:b;

    从刚开始用3个变量,再用公式推导消除一个变量来看:

    此时共有变量[a,b,c]

    1.c=a^b;
    2.b=a;
    //其实到第3步运行之前,a的值是一直没有改变过的,
    //所以ca,可以推导出:(ab)^a,这个时候要注意了,
    //此时的b还是在c中的b,而不是第2步已经改变了值得b.(这不是引用类型...不是第2步b的值改了,c的值也跟着改)
    //这个地方不太好理解,中心思想就是:先把a和b的关系放兜里,这个兜就是c,并且能通过一种运算,和未改变的a值,
    //来反求出b的值;
    3.a=c^a;

    先将第2步"b=a;",修改一下
    因为a^0 = a;可以写为:b=a^0;
    因为b^b = 0;可以写为:b = abb;
    再加上括弧;

    1.c0=a0^b0;
    2.b1=(a0b0)b0;
    3.a1=(a0b0)b1;

    其实这个时候,将c替换成a,是完全可以的,
    因为c除了第1步被赋值之后,就没有再改过值.
    //a0和a1都是变量a,只是为了区分a值改变了一次,就会将a0写为a1

    1.a1=a0^b0;
    2.b1=a1^b0;
    3.a1=a1^b1;

    一共3个赋值动作,第1个赋值为了建立关系,剩下2个,就是赤裸裸的交换数据了.

    感受一下,a和b,在这个过程中一共值发生了几次变化.

    感觉最后两步讲的还是有点模糊,希望哪位大虾给完善下...

    Visual Studio C# Interactive

    > var a = 5; var b = 9;
    
    . Console.WriteLine("b = {0}",(a ^ b) ^ b);
    . Console.WriteLine("a = {0}",(a ^ b) ^ a);
    
    //输出
    a = 9
    b = 5
    > 
    ```
    
    ![](https://img2018.cnblogs.com/blog/533973/202001/533973-20200117092636069-2110441739.png)
    
    
    
    GG ... 晚安...
    
    ### 扩展
    * 逻辑运算["~","&","|","^"]
    
     
    ### 编辑时间列表
    [1].二〇一六年十一月十五日 18:17:41
    [2].贰零贰零年-一月十五号 晚
  • 相关阅读:
    VS中添加搜索路径和链接库的方法
    hive多分隔符支持
    shell 遍历目录下的所有文件
    使用ansible控制Hadoop服务的启动和停止【转】
    Shell中的括号有其特殊的用法
    shell中括号[]的特殊用法 linux if多条件判断
    Linux中rz和sz命令用法详解
    vim 去掉自动注释和自动回车
    ping判断局域网ip使用情况
    shell判断有效日期
  • 原文地址:https://www.cnblogs.com/love-zf/p/12199326.html
Copyright © 2011-2022 走看看