i = i + j ;
j = i - j ;
i = i - j ;
上面的代码是做什么用的?有人能用其他代码写出同样的操作吗?
谢谢。
i
和 j
值的技术,不需要创建临时变量。这是一种内存优化的形式。a = 3
和b = 2
(二进制)设置,并尝试一下a = a ^ b :: a = 110 ^ 100 = 10
a与b进行异或运算:: a = 110 ^ 100 = 10
现在 a = 10
和 b = 100
或者 a = 2
和 b = 3
现在,a = 10
且 b = 100
或者 a = 2
且 b = 3
Welcome to bits!
欢迎来到位操作!
它交换了i
和j
的值。假设它们的初始值为a
和b
,那么这些语句将被计算为:
i = a + b;
j = (a + b) - b; // = a
i = (a + b) - a; // = b
回答你问题的第二部分,一个替代方案(在现实生活中的非面试场合很可能采取的方法)看起来会像这样:int tmp = i;
i = j;
j = tmp;
最常用的交换方法是使用临时变量:
T swap = i;
i = j;
j = swap;
swap = null; // or let it fell out of scope
i = i + j ;
j = i - j ; // i + j - j = i
i = i - j ; // i + j - (i + j - j) = j
如果以下条件成立,则此黑客技巧有效:
i
和 j
是整数,它们的和在2147483647和-2147483648之间。i
和 j
是长整数,它们的和在9223372036854775807和-9223372036854775808之间。有一个类似的xor交换黑客技巧。
i = i ^ j;
j = i ^ j; // i ^ j ^ j = i
i = i ^ j; // i ^ j ^ i ^ j ^ j = j
这是一个轻微变化的版本:
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
只有在以下情况下,此黑客才有效:
i != j
,两个索引引用相同的元素并互相抵消。const int tmp = i;
i = j;
j = tmp;
这假设类型为int
。请注意,在计算中存在整数溢出/下溢风险时,该交换技巧并不安全。此外,它也不是很明确,读者需要非常努力地思考才能理解发生了什么(或者问别人)。
它交换它们 - 但如果您使用不同的变量名称使事情更清晰,那么更容易看出来:
int originalI = ...;
int originalJ = ...;
int tmp = originalI + originalJ;
int newJ = tmp - originalJ;
int newI = tmp - newJ;
int originalI = ...;
int originalJ = ...;
int tmp = originalI + originalJ;
int newJ = originalI + originalJ - originalJ;
int newI = originalI + originalJ - (originalI + originalJ - originalJ);
...并简化:
int originalI = ...;
int originalJ = ...;
int tmp = originalI + originalJ;
int newJ = originalI;
int newI = originalJ;
...并删除临时变量:
int originalI = ...;
int originalJ = ...;
int newJ = originalI;
int newI = originalJ;
看起来它在交换 i
和 j
。
它交换变量。
另一种方法:
i ^= j;
j ^= i;
i ^= j;
i = i + j;
j = i - j;
i = i - j;
j = i;
i = i - j
,在伪代码中相当于:i = originalSum - originalValueOf_i; //原始的j
。
所以,基本上,所有原始代码都等同于一个交换例程,即:
tempVal = i;
i = j;
j = tempVal;
我们甚至可以尝试一个涉及正负值的示例来证明这是正确的:
i = -24.3;
j = 10.4;
//原始代码:
i = i + j; //i现在等于-13.9
j = i - j; //j现在等于-13.9 - 10.4,即-24.3(我们的原始i值)。
i = i - j; //i现在等于-13.9 -(-24.3),即10.4(我们的原始j)。
有人可能会按照他/她的方式编写您发布的交换,以避免方法调用开销、声明新变量等,但如果您要频繁交换值,则反复使用您发布的代码可能会变得棘手。像上面显示的交换例程是相当常见的。
它交换了i
和j
的值:
i = i+j;
j = (original_i + j) - j = original_i;
i = original_i + original_j - original_i = original_j;
是的,有其他方法可以完成此操作。
i 获得 j 的值。而 j 保持它的值。
int temp = i; i = j; j = temp
。 - ring bearer