算法 | 如何不使用用额外变量交换两个数?

174 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情

前言

本文主要介绍如何不使用用额外变量交换两个数,交换两个数我们都知道,最简单的设置一个临时变量,先把其中一个数赋值给临时变量再交换即可,那么如果不使用临时变量该如何做呢?

在实现之前,我们先来介绍下异或运算。

异或运算

异或运算又称无进位运算,如果两个值不相同,则异或结果为1。如果两个值相同,异或结果为0。

运算规则

  1. 基本运算
0 ^ 0 = 0
0 ^ N = N
N ^ 0 = N
N ^ N = 0
  1. 交换律
A ^ B = B ^ A
  1. 结合律
(A ^ B) ^ C = A ^ ( B ^ C ) 

数值交换

假如A = 10B = 20,怎么在不借助额外变量的情况下进行交换呢?

先看下用户异或运算实现的结果:

A = A ^ B
B = A ^ B
A = A ^ B

只需要执行三遍A ^ B,就能实现。

证明

这三行代码在执行的过程中,发生了什么?为什么执行3遍,就能交换?

我们来看下交换的过程,现在假如A = aB = b

第1次A ^ B,代入AB的值可以得到,A = a ^ b

第2次A ^ B,代入AB的值可以得到,B = (a ^ b) ^ b,使用结合律可得B = a ^ (b ^ b) = a ^ 0 = a,此时,B = a

第3次A ^ B,代入AB的值可以得到,A = (a ^ b) ^ a,使用交换律和结合律可得A = (a ^ a ) ^ b = 0 ^ b = b,此时A = b

从上面步骤可以看到,AB的值经过3次异或之后,就发生了交换。

注意

在一些算法中,我们经常对数组中的两个数进行交换,例如:

public static void swap(int[] arr, int i, int j) {
    arr[i] = arr[i] ^ arr[j];
    arr[j] = arr[i] ^ arr[j];
    arr[i] = arr[i] ^ arr[j];
}

在交互数组的两个数时,要特别注意 ij不能相等,如果相等的话,最后结果都会等于0

因为在数组中,如果ij相等的话,arr[i]arr[j]指向的是同一块内存地址,在执行第一遍异或运算的时候,结果为0,此时arr[i]arr[j]因为是指向的内存地址是一样的,所以也直接变成了0

总结

本文主要介绍如何不使用用额外变量交换两个数,在实现过程中使用了异或运算,并对异或运算进行了简单的介绍,使用异或运算来实现两个数的交互,最后介绍了在对数组交换是的注意事项。