zoukankan      html  css  js  c++  java
  • 一道面试题:用多种方法实现两个数的交换

    很多程序经常使用的最普通,比较常见的,也是比较简单的一个算法

    1、普通方法,借助一个额外内存变量实现交换:

    #include <iostream>
    using namespace std;
    
    int main(int argc, const char * argv[]) {
        int a;
        int b;
        int temp;
        
        a = 100;
        b = 200;
        
        cout << "a = " << a << " b = " << b << endl;
        
        //swap 交换
        temp = a;
        a = b;
        b = temp;
        
        cout << "a = " << a << " b = " << b << endl;
        
        return 0;
    }

    老掉牙的套路

    2、额外内存方法,做成函数

    #include <iostream>
    using namespace std;
    
    void swap(int, int);
    
    int main(int argc, const char * argv[]) {
        int a;
        int b;
        
        a = 100;
        b = 200;
        
        cout << "a = " << a << " b = " << b << endl;
        
        swap(a, b);
        
        cout << "a = " << a << " b = " << b << endl;
        
        return 0;
    }
    
    void swap(int a, int b)
    {
        int temp;
        //swap 交换
        temp = a;
        a = b;
        b = temp;
    }

    a = 100 b = 200

    a = 100 b = 200

    Program ended with exit code: 0

    没有发生改变,不起作用,还是老生常谈了。因为传递的是参数的拷贝,交换的是拷贝,对原来的数,没有任何影响。改正:

    #include <iostream>
    using namespace std;
    
    void swap(int *, int *);
    
    int main(int argc, const char * argv[]) {
        int a;
        int b;
        
        a = 100;
        b = 200;
        
        cout << "a = " << a << " b = " << b << endl;
        
        swap(&a, &b);
        
        cout << "a = " << a << " b = " << b << endl;
        
        return 0;
    }
    
    void swap(int *a, int *b)
    {
        int temp;
        //swap 交换
        temp = *a;
        *a = *b;
        *b = temp;
    }

    a = 100 b = 200

    a = 200 b = 100

    Program ended with exit code: 0

    3、使用 c 语言里的宏定义(宏函数)

    复习笔记回忆:#define的用法

     

    #include <iostream>
    using namespace std;
    #define SWAP(x, y, z) ((z) = (x), (x) = (y), (y) = (z))
    
    int main(int argc, const char * argv[]) {
        int a;
        int b;
        int c;
        
        a = 10;
        b = 200;
        
        cout << "a = " << a << " b = " << b << endl;
        
        SWAP(a, b, c);
        
        cout << "a = " << a << " b = " << b << endl;
        
        return 0;
    }

    a = 10 b = 200

    a = 200 b = 10

    Program ended with exit code: 0

    4、使用 c++独有的引用

    #include <iostream>
    using namespace std;
    
    void swap(int &, int &);
    
    int main(int argc, const char * argv[]) {
        int a;
        int b;
        
        a = 100;
        b = 200;
        
        cout << "a = " << a << " b = " << b << endl;
        
        swap(a, b);
        
        cout << "a = " << a << " b = " << b << endl;
        
        return 0;
    }
    
    void swap(int &a, int &b)
    {
        int temp;
        //swap 交换
        temp = a;
        a = b;
        b = temp;
    }

    不使用额外内存的方法,数学方法

    不开辟新的内存变量实现交换(阿里巴巴的面试题,有时候为了追求机器的高性能,高效率,节约内存,一般用这种算术技巧,加减法可以,乘除法也可以,使用位操作也可以)

    5、算术运算方法

    #include <iostream>
    using namespace std;
    
    int main(void)
    {
        int a = 100;
        int b = 200;
        
        cout << "a = " << a << " b = " << b << endl;
        
        a = a + b;//把 a,b 的和给 a,此时的 a 是a+b 的和
        b = a - b;//等价于把 a 赋值给 b,此时的 b 是 a 的值
        a = a - b;//等价于把 b 赋值给 a,完成了交换
        
        cout << "a = " << a << " b = " << b << endl;
        
        return 0;
    }

    a = 100 b = 200

    a = 200 b = 100

    Program ended with exit code: 0

    同样乘除也可以实现,其实就是小学生的算术,只是想不到而已。

        a = a * b;
        b = a / b;
        a = a / b;
        

    6、位运算方法

    相关复习c 语言的位运算符复习

    异或运算有这样一个性质:

    a ^ b ^ a;

    也就是 x 异或 y 再异或 x,最后的结果是 y(中间的变量被提出)

    例如:a=3,即11(2);b=4,即100(2)。
    想将a和b的值互换,可以用以下赋值语句实现:
        a=a∧b;
        b=b∧a;//相当于b = b ^ a ^ b;最后把 a 提出,给了 b
        a=a∧b;//相当于,a = a ^ b ^ a;,最后把 b 提出,给了a

    a=011(2)(∧)b=100(2)
    a=111(2)(a∧b的结果,a已变成7)(∧)b=100(2)
    b=011(2)(b∧a的结果,b已变成3)(∧)a=111(2)

    a=100(2)(a∧b的结果,a已变成4)

    等效于以下两步:
        ① 执行前两个赋值语句:“a=a∧b;”和“b=b∧a;”相当于b=b∧(a∧b)。
        ② 再执行第三个赋值语句: a=a∧b。由于a的值等于(a∧b),b的值等于(b∧a∧b),

    因此,相当于a=a∧b∧b∧a∧b,即a的值等于a∧a∧b∧b∧b,等于b。不推荐这样写,也不推荐在项目中使用!

    C 语言的一条语句中,最好是,一个变量的值只允许改变一次,像x = x++ 这种代码都是未定义行为。在C语言里没有哪条规则保证以上写法是永远正确的。
    另外,用异或交换变量既不会加快运行速度(反而更慢,六读三写加三次异或),也不会节省空间(中间变量tmp 通常会用寄存器,而不是内存空间存储)。

    这个技巧的意义完全在于应付变态的面试,知道就行了,绝对不要放在产品代码中。所以说这只是“面试技巧”。

    补充其他性质:

    1、交换律

    2、结合律(即(a^b)^c == a^(b^c))

    3、对于任何数x,都有x^x=0,x^0=x

    4、自反性 A XOR B XOR B = A xor  0 = A

    欢迎关注

    dashuai的博客是终身学习践行者,大厂程序员,且专注于工作经验、学习笔记的分享和日常吐槽,包括但不限于互联网行业,附带分享一些PDF电子书,资料,帮忙内推,欢迎拍砖!

  • 相关阅读:
    数据库(SQL Server)管理数据库表~新奇之处
    疯狂C#~伴随着我的库存管理¥
    书中的银行,我们一起奋斗的C#,只因乐在其中~
    MyBatis的经典案例
    Spring MVC的配置文件(XML)的几个经典案列
    Spring MVC注解的一些案列
    WebService的一些案例
    AOP面向切面编程的四种实现
    Struts 2的OGNL的根对象
    Struts 2的拦截器(Interceptor)总结
  • 原文地址:https://www.cnblogs.com/kubixuesheng/p/4104800.html
Copyright © 2011-2022 走看看