大数据Java-交换变量的 3 种方式

本话题要讨论的是一道面试题目:交换两个变量的值。两个变量而已,看似再简单不过了,不过一道简单的题目可以使用多种方式来完成, 其中有比较普通的实现, 也有相对高明的实现,虽然是一道简单的题目,但是通过面试者对该题目的认知能力,就可以看出面试者的水平。

重点摘要:

1 通过中间变量交换。

2 通过求和与求差交换。

3 通过异或交换。

通过第 3 个变量

首先,我们给出最简单的方式。

【例】 交换两个变量的值。

package chapter2;
2.
3. public class Swap {
4. public static void main(String[] args) {
5. int x = 5;
6. int y = 10;
7. swap(x, y);
8. System.out.println(x);
9. System.out.println(y);
10. Value v = new Value(5, 10);
11. swap(v);
12. System.out.println(v.x);
13. System.out.println(v.y);
14. }
15. //无效的交换
16. public static void swap(int x, int y) {
17. int temp = x;
18. x = y;
19. y = temp;
20. }
21. //有效的交换
22. public static void swap(Value value) {
23. int temp = value.x;
24. value.x = value.y;
25. value.y = temp;
26. }
27.}
28.
29.class Value {
30. int x;
31. int y;
32.
33. public Value(int x, int y) {
34. this.x = x;
35. this.y = y;
36. }
37.}

程序运行结果如下:

5
10
10
5

这个程序同时给出了有效的交换(第22~26 行)与无效的交换(第16~20 行)。因为形参的改变是无法反作用于实参的,所以不能使用变量交换的方式,而是要使用通过引用来修改其成员变量的方式。这就类似与C / C++的语言中的指针效果。

通过相加的方式

 

通过第3个临时变量,可以成功交换两个变量的值,不过,有时,面试题目的要求会比较苛刻,就是不允许借助于临时变量。这样,就有些复杂了。
【例】 交换两个变量的值2。

package chapter2;
2.
3. public class Swap2 {
4. public static void main(String[] args) {
5. Value v1 = new Value(5, 10);
6. swap(v1);
7. System.out.println("v1
的交换结果:
");
8. System.out.println(v1.x);
9. System.out.println(v1.y);
10. Value v2 = new Value(1200000000, 1500000000);
11. swap(v2);
12. System.out.println("v2
的交换结果:
");
13. System.out.println(v2.x);
14. System.out.println(v2.y);
15. Value v3 = new Value(-1200000000, -1500000000);
16. swap(v3);
17. System.out.println("v3
的交换结果:
");
18. System.out.println(v3.x);
19. System.out.println(v3.y);
20. }
21.
22. public static void swap(Value v) {
23. v.x = v.x + v.y;
24. v.y = v.x - v.y;
25. v.x = v.x -v.y;
26. }
27.}

程序运行结果如下:

v1的交换结果:

10
5

v2的交换结果:

1500000000
1200000000

v3的交换结果:

-1500000000
-1200000000

核心部分就是swap 方法(第22~26 行),该方法的3 条语句解释为:

v.x = v.x + v.y; //
将
v.x
与
v.y
的和存储在
v.x
中
v.y = v.x - v.y; //v.x – v.y
的值就是以前
v.x
的值,赋值给
v.y
v.x = v.x -v.y; //v.x – v.y
的值就是以前
v.y
的值,赋值给
v.x

这样,没有通过临时变量,也同样交换了两个变量的值。也许上面的方法一时不太容易理解,那么可以这样考虑:

int z = v.x + v.y;v.y = z – v.y;v.x = z - v.y;

只不过这里使用另外一个变量z,而上面使用v.x 来存储v.x 与v.y 的和,但是交换的效果是相同的。
注意程序的第10 行与第15 行,v.x 与v.y 的初始值非常大(小),这样一来,当执行swap方法时(以第10 行为例):

v.x = v.x + v.y;

十六进制求和如下所示:

47868c00
(
v.x
)
+ 59682f00
(
v.y
)
结果:
a0eebb00
(
v.x + v.y
)

注意这个结果的最高位为1,结果为负数(十进制值为1594967296,也就是v.x 与v.y 的和已经超过了int 类型的最大(小)值,发生溢出。
执行接下来的语句:

v.y = v.x - v.y;

这个计算就是使用溢出后的值1594967296减去v.y(1500000000),从int 类型的求差角度来说,结果再一次溢出了,十六进制求差如下所示:

a0eebb00
(
v.x + v.y
)
 
59682f00
(
v.y
)
结果:
47868c00
(结果
v.y
)

经过两次溢出以后,又再次得出了我们期望的值。同样,swap 方法的第3 条语句:

v.x = v.x -v.y;
a0eebb00
(
v.x + v.y
)
 
47868c00
(
v.y
)

结果:59682f00(结果v.x)
也是发生了溢出,不过最后的差值也得出了期望的结果。可以看出,当两个数之和很大(小)时,虽然发生了溢出,不过最后还是阴差阳错地得到了正确的结果。尽管结果正确,这种相加的方式还不算十分可取。

通过异或的方式

位异或运算符(^)有这样一个性质,就是两个整型数据x 与y,有:

(x ^ y ^ y) == x

这说明,如果一个变量x 异或另外一个变量y 两次,结果为x。通过这一点,可以实现交换变量的值。

【例】交换两个变量的值3。

  1. 1.package chapter2;
    2.
    3. public class Swap3 {
    4. public static void main(String[] args) {
    5. Value v = new Value(5, 10);
    6. swap(v);
    7. System.out.println(v.x);
    8. System.out.println(v.y);
    9. }
    10.
    11. public static void swap(Value v) {
    12. v.x = v.x ^ v.y;
    13. v.y = v.x ^ v.y;
    14. v.x = v.x ^ v.y;
    15. }
    16.}

程序运行结果如下:

10
5

swap 方法(第11~15 行)并不复杂,只有3 条语句:

v.x = v.x ^ v.y; (1)
v.y = v.x ^ v.y; (2)
v.x = v.x ^ v.y; (3)

可以这样看:执行(1)后,v.x 的值就是v.x(异或运算之前的值)与v.y 异或后的结果。类似数学上的代入法,将v.x(值为v.x ^ v.y)代入(2)中,于是(2)赋值运算符(=右侧的表达式相当于:

v.x ^ v.y ^ v.y //v.x与v.y都是运算之前的值

这个值就是v.x(异或运算之前的值)、然后赋值给左侧的v.y。此时,v.y 的值就是异或运算之前v.x 的值。然后将v.x(值为v.x ^ v.y)、v.y(值为异或运算之前v.x 的值)代入(3)中赋值运算符右侧,代入后表达式相当于:

v.x ^ v.y ^ v.x //v.x与v.y都是运算之前的值

。推荐:http://www.lemonpai.com/1508.html

这个值就是v.y,然后赋值给v.x,至此,完成两个变量的交换。异或方式要比相加方式更加可取,因为异或运算不涉及溢出。综合这3 种方式而言,第1 种方式最容易理解,第3 种方式相对成熟老练,如果是个人编写程序,建议还是使用最简单的方式,这样不容易出错,而且代码具有可读性,便于后期的维护,如果是在面试过程中,那就可以选择第3 种方式来证明下自己的能力。

总结:

  1. 1.      一个变量x 异或另一个变量y 两次,结果的值为x。
    2. 异或运算可以交换两个变量的值,并且这种方式比相加交换的方式更可取些。

举一反三
既然相加(第2 种方式)能够实现交换两个变量的值,那么相减肯定也能实现。编写一个程序,不要借助第3 个临时变量,实现相减操作交换两个变量的值。

本文作者梁勇出自柠檬派,请注明出处

时间: 2024-10-06 01:59:03

大数据Java-交换变量的 3 种方式的相关文章

从0开始学大数据-Java运算符(3)

我们从零开始学习大数据技术,从java基础,到Linux技术涉猎,再深入到大数据技术的Hadoop.Spark.Storm技术,最后到大数据企业平台的搭建,层层递进,由点到面!希望技术大牛能过来指导学习. 上一节了解Java基础语法,本节我们开始学习Java基础-运算符,将会围绕以下几个知识点进行展开学习: 算术运算符 赋值运算符 比较运算符 逻辑运算符 位运算符 三元运算符 PS:开始之前我们先针对上节数据类型中补充的几个小问题 一.数据类型中补充的几个小问题 1.byte值的问题 byte

从零开始学大数据-Java基础-switch语句(6)

我们从零开始学习大数据技术,从java基础,到Linux技术涉猎,再深入到大数据技术的Hadoop.Spark.Storm技术,最后到大数据企业平台的搭建,层层递进,由点到面!希望技术大牛能过来指导学习. 上一节学习了流程控制语句,本节学习switch语句. 开始之前,我们先看一下上节的练习题. 一.练习题 if语句格式的练习: 1.获取两个数据中较大的值 2.判断一个数据是奇数还是偶数,并输出 程序执行结果如下: 二.switch语句 流程控制语句的选择结构 1 选择结构(也被称为分支结构)

【全集】大数据Java基础

课程介绍 本课程是由猎豹移动大数据架构师,根据Java在公司大数据开发中的实际应用,精心设计和打磨的大数据必备Java课程.通过本课程的学习大数据新手能够少走弯路,以较短的时间系统掌握大数据开发必备语言Java,为后续大数据课程的学习奠定了坚实的语言基础. 适用人群 1.想学大数据没有语言基础的学员 2.想学大数据没有Java语言基础的学员 3.转行想学大数据的学员 4.了解Java,大数据Java知识体系不完整的学员 课程视频下载地址(视频完整,无加密) 链接:https://pan.baid

从0开始学大数据-Java基础-三元运算符/键盘录入(4)

我们从零开始学习大数据技术,从java基础,到Linux技术涉猎,再深入到大数据技术的Hadoop.Spark.Storm技术,最后到大数据企业平台的搭建,层层递进,由点到面!希望技术大牛能过来指导学习. 上一节了解Java运算符,其中三元运算符没有做讲解,本节我们开始学习Java基础-三元运算符/键盘录入,将会围绕以下几个知识点进行展开学习: 三元运算符 键盘录入数据 一.运算符 1.三元运算符 接着上一节的话题运算符,本节讲三元运算符,在讲三元运算符之前,可能会有很多朋友会问,是不是有一元运

【LINK】程序员想玩转大数据:需要知晓的12种工具

http://www.csdn.net/article/2012-12-20/2813054-Database http://blog.csdn.net/qjfpjie/article/details/8439119 [LINK]程序员想玩转大数据:需要知晓的12种工具

更多免费初级中级高级大数据java视频教程下载 加(微***信((号keepper,请备注java或扫下面2二3维4码架构师148讲视频教程(71-80讲)

更多免费初级中级高级大数据java视频教程下载 加(微***信((号keepper,请备注java或扫下面2二3维4码架构师148讲视频教程(71-80讲)java视频教程第71节:ActiveMQ入门和消息中间件.avijava视频教程第72节:JMS基本概念和模型.avijava视频教程第73节:JMS的可靠性机制.avijava视频教程第74节:JMS的API结构和开发步骤.avijava视频教程第75节:Broker的启动方式.avijava视频教程第76节:ActiveMQ结合Spri

临近毕业:AndroidVS大数据Java的offer,我到底应该怎么选?

拿到几份offer,我该如何选择? 先简单介绍一下我的情况: 本人现在大四,即将毕业.苏州某普通本科在校生.目前已经确定拿到了南京一个中型创业公司的offer,公司安排到了大数据Java岗.还有一个offer就是上海某4G/5G智能终端创新研发平台Android应用开发岗.其他的一些微创企业的面试offer就不提了. 在校期间做的项目很杂,php的后端,老三大件的前端,android,片上代码都有写过,不过专攻android,也学的做的最多,可能跟入行多年的前辈们没得比,不过在同水平选手中算是a

几种排序算法及Java实现排序的几种方式

几种排序算法 下面的例子介绍了4种排序方法: 冒泡排序, 选择排序, 插入排序, 快速排序 1 package date201709.date20170915; 2 3 public class SortUtil { 4 5 private static int quickSortTimes = 1; 6 7 /** 8 * 冒泡排序:<br> 9 * 两层循环,每次循环比较前后两个元素,如果他们的顺序错误就把他们交换过来,一次循环后最终会把最大的数沉到数列的末端<br> 10 *

java连接Hive的几种方式

测试环境 Hadoop 0.20.2版本.Hive-0.5.0版本.JDK1.6 1.一般来说我们对hive的操作都是通过cli来进行,也就是Linux的控制台,但是,这样做本质上是每个连接都存放一个元数据,各个之间都不相同,所以,对于这样的模式我建议是用来做一些测试比较合适,并不适合做产品的开发和应用. 2.JDBC连接的方式,当然还有其他的连接方式,比如ODBC等, 这种方式很常用,可以在网上随便找到,就不再累赘了. 不稳定,经常会被大数据量冲挂,不建议使用. 3.这种方式是直接利用Hive