溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

大數(shù)據(jù)Java-交換變量的 3 種方式

發(fā)布時間:2020-06-18 14:35:14 來源:網(wǎng)絡(luò) 閱讀:690 作者:ws小馬哥 欄目:大數(shù)據(jù)

 

本話題要討論的是一道面試題目:交換兩個變量的值。兩個變量而已,看似再簡單不過了,不過一道簡單的題目可以使用多種方式來完成, 其中有比較普通的實現(xiàn), 也有相對高明的實現(xiàn),雖然是一道簡單的題目,但是通過面試者對該題目的認(rèn)知能力,就可以看出面試者的水平。

重點(diǎn)摘要:

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.}


程序運(yùn)行結(jié)果如下:

5
10
10
5


這個程序同時給出了有效的交換(第2226 行)與無效的交換(第1620 行)。因為形參的改變是無法反作用于實參的,所以不能使用變量交換的方式,而是要使用通過引用來修改其成員變量的方式。這就類似與C / C++的語言中的指針效果。

通過相加的方式

 

通過第3個臨時變量,可以成功交換兩個變量的值,不過,有時,面試題目的要求會比較苛刻,就是不允許借助于臨時變量。這樣,就有些復(fù)雜了。
【例】 交換兩個變量的值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
的交換結(jié)果:
");
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
的交換結(jié)果:
");
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
的交換結(jié)果:
");
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.}


程序運(yùn)行結(jié)果如下:

v1的交換結(jié)果:

10
5

v2的交換結(jié)果:

1500000000
1200000000

v3的交換結(jié)果:

-1500000000
-1200000000


核心部分就是swap 方法(第2226 行),該方法的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 的初始值非常大(?。?,這樣一來,當(dāng)執(zhí)行swap方法時(以第10 行為例):

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


 

十六進(jìn)制求和如下所示:

47868c00
(
v.x
)
+ 59682f00
(
v.y
)
結(jié)果:
a0eebb00
(
v.x + v.y
)


注意這個結(jié)果的最高位為1,結(jié)果為負(fù)數(shù)(十進(jìn)制值為1594967296,也就是v.x v.y 的和已經(jīng)超過了int 類型的最大(?。┲担l(fā)生溢出。
執(zhí)行接下來的語句:

 

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


這個計算就是使用溢出后的值1594967296減去v.y1500000000),從int 類型的求差角度來說,結(jié)果再一次溢出了,十六進(jìn)制求差如下所示:

a0eebb00
(
v.x + v.y
)
 
59682f00
(
v.y
)
結(jié)果:
47868c00
(結(jié)果
v.y
)


經(jīng)過兩次溢出以后,又再次得出了我們期望的值。同樣,swap 方法的第3 條語句:

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


a0eebb00
(
v.x + v.y
)
 
47868c00
(
v.y
)


結(jié)果:59682f00(結(jié)果v.x
也是發(fā)生了溢出,不過最后的差值也得出了期望的結(jié)果??梢钥闯?,當(dāng)兩個數(shù)之和很大(?。r,雖然發(fā)生了溢出,不過最后還是陰差陽錯地得到了正確的結(jié)果。盡管結(jié)果正確,這種相加的方式還不算十分可取。

 

通過異或的方式

位異或運(yùn)算符(^)有這樣一個性質(zhì),就是兩個整型數(shù)據(jù)x y,有:

(x ^ y ^ y) == x

 

這說明,如果一個變量x 異或另外一個變量y 兩次,結(jié)果為x。通過這一點(diǎn),可以實現(xiàn)交換變量的值。

【例】交換兩個變量的值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.}

程序運(yùn)行結(jié)果如下:

10
5


swap 方法(第1115 行)并不復(fù)雜,只有3 條語句:

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


可以這樣看:執(zhí)行(1)后,v.x 的值就是v.x(異或運(yùn)算之前的值)與v.y 異或后的結(jié)果。類似數(shù)學(xué)上的代入法,將v.x(值為v.x ^ v.y)代入(2)中,于是(2)賦值運(yùn)算符(=右側(cè)的表達(dá)式相當(dāng)于:

v.x ^ v.y ^ v.y //v.x與v.y都是運(yùn)算之前的值


這個值就是v.x(異或運(yùn)算之前的值)、然后賦值給左側(cè)的v.y。此時,v.y 的值就是異或運(yùn)算之前v.x 的值。然后將v.x(值為v.x ^ v.y)、v.y(值為異或運(yùn)算之前v.x 的值)代入(3)中賦值運(yùn)算符右側(cè),代入后表達(dá)式相當(dāng)于:

v.x ^ v.y ^ v.x //v.x與v.y都是運(yùn)算之前的值

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


這個值就是v.y,然后賦值給v.x,至此,完成兩個變量的交換。異或方式要比相加方式更加可取,因為異或運(yùn)算不涉及溢出。綜合這3 種方式而言,第1 種方式最容易理解,第3 種方式相對成熟老練,如果是個人編寫程序,建議還是使用最簡單的方式,這樣不容易出錯,而且代碼具有可讀性,便于后期的維護(hù),如果是在面試過程中,那就可以選擇第3 種方式來證明下自己的能力。

總結(jié):

  1. 1.      一個變量x 異或另一個變量y 兩次,結(jié)果的值為x
    2. 異或運(yùn)算可以交換兩個變量的值,并且這種方式比相加交換的方式更可取些。

 

舉一反三
既然相加(第2 種方式)能夠?qū)崿F(xiàn)交換兩個變量的值,那么相減肯定也能實現(xiàn)。編寫一個程序,不要借助第3 個臨時變量,實現(xiàn)相減操作交換兩個變量的值。

本文作者梁勇出自檸檬派,請注明出處

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI