1. 程式人生 > 實用技巧 >不使用臨時變數交換2個數字的三種方法

不使用臨時變數交換2個數字的三種方法

題目

編寫一個函式,不用臨時變數,直接交換numbers = [a, b]中a與b的值。
示例:

輸入: numbers = [1,2]
輸出: [2,1]

提示:

  • numbers.length == 2

實現程式碼及解題思路

注意:方法二隻是思路,實際會存在溢位問題。

/**
    * 方法一:根據差值, 來移動a, b
    * 如下圖所示, a, b為數軸上2點, 可以利用a, b之間的距離不變, 來交換a和b
    *
    * ------------
    * a          b
    *
    * b = b - a; // 此時b是線段ab長
    * a = a + b; // 此時a到原b位置
    * b = a - b; // 此時b到原a位置
    * @param numbers
    * @return
    */
public int[] swapNumbers_1(int[] numbers) {
    if (numbers.length != 2) return numbers;
    numbers[1] = numbers[1] - numbers[0];
    numbers[0] = numbers[0] + numbers[1];
    numbers[1] = numbers[0] - numbers[1];

    return numbers;
}

/**
    * 方法二:用b作為中點,先將a移動到以b為中點的對稱位置a1=2b-a,
    * 然後將b以b為中點移動至a1的對稱位置,也就是原來a所在位置,這樣b1=a0,
    * 再將a從a1移動至a1和b1中點,也就是原來b所在位置,這樣a2=b0
    *
    * a = 2*b - a;
    * b = 2*b - a;
    * a = (a + b) / 2;
    *
    * @note 該方法理論上可行,不過存在溢位的問題,
    * 當numbers[1] * 2溢位,或者該乘積-numbers[0]溢位,會導致儲存的中間結果出錯
    * 考慮,如果用a/b中點作為錨點,雖然不會溢位,不過在/2運算時,可能存在損失精度問題
    * 另外,第一次+運算,有可能產生溢位問題
    * a = (a + b) / 2;
    * b = 2a - b;
    * a = 2a - b;
    */
public int[] swapNumbers_2(int[] numbers) {
    if (numbers.length != 2) return numbers;

    // 以b為中點,交換ab
    /*
    numbers[0] = numbers[1] * 2 - numbers[0];
    numbers[1] = numbers[1] * 2 - numbers[0];
    numbers[0] = (numbers[0] + numbers[1]) / 2;
        */

    // 以ab中點為中點,交換ab
    numbers[0] = (numbers[0] + numbers[1]) / 2;
    numbers[1] = 2*numbers[0] - numbers[1];
    numbers[0] = 2*numbers[0] - numbers[1];

    return numbers;
}

/**
    * 異或運算
    * 0^0 = 0
    * 0^1 = 1
    * 1^0 = 1
    * 1^1 = 0
    * 異或運算a^b可以理解成,消去a∪b中與ab相同的部分(a∩b),即a^b = a∪b - a∩b,這裡a、b都是集合
    * a = a^b; // 此時a1 = a∪b -a∩b, 也就是a和b不相交的所有元素
    * b = a^b; // 此時b1 = a1∪b - a1∩b = a0,也就是原來的a
    * a = a^b; // 此時a2 = a1∪b1 - a1∩b1 = b0,也就是原來的b
    *
    */
public int[] swapNumbers(int[] numbers) {
    if (numbers.length != 2) return numbers;
    numbers[0] = numbers[0]^numbers[1];
    numbers[1] = numbers[0]^numbers[1];
    numbers[0] = numbers[0]^numbers[1];

    return numbers;
}

面試題 16.01. 交換數字 | LeetCode