DeepSeek 不用额外变量交换两个整数的值 go实现
·
在 Go 语言中,有多种方法可以交换两个整数的值而不使用额外变量:
方法1:使用算术运算(最常用)
package main
import "fmt"
func main() {
a, b := 10, 20
fmt.Printf("交换前: a=%d, b=%d\n", a, b)
// 使用加减法
a = a + b // a = 30
b = a - b // b = 30 - 20 = 10
a = a - b // a = 30 - 10 = 20
fmt.Printf("交换后: a=%d, b=%d\n", a, b)
}
方法2:使用异或运算(避免溢出)
package main
import "fmt"
func main() {
a, b := 10, 20
fmt.Printf("交换前: a=%d, b=%d\n", a, b)
// 使用异或运算
a = a ^ b // a = 10 ^ 20
b = a ^ b // b = (10 ^ 20) ^ 20 = 10
a = a ^ b // a = (10 ^ 20) ^ 10 = 20
fmt.Printf("交换后: a=%d, b=%d\n", a, b)
}
方法3:Go 特有的元组赋值(最简单)
package main
import "fmt"
func main() {
a, b := 10, 20
fmt.Printf("交换前: a=%d, b=%d\n", a, b)
// Go 特有的元组赋值(实际上编译器可能使用临时变量,但代码中没有)
a, b = b, a
fmt.Printf("交换后: a=%d, b=%d\n", a, b)
}
方法4:使用函数封装
方式1:返回交换后的值
package main
import "fmt"
// 返回交换后的两个值
func swap(a, b int) (int, int) {
a = a ^ b
b = a ^ b
a = a ^ b
return a, b
}
// 或者使用加减法
func swapArithmetic(a, b int) (int, int) {
a = a + b
b = a - b
a = a - b
return a, b
}
func main() {
x, y := 10, 20
fmt.Printf("交换前: x=%d, y=%d\n", x, y)
x, y = swap(x, y)
fmt.Printf("交换后: x=%d, y=%d\n", x, y)
}
方式2:使用指针修改原值
package main
import "fmt"
// 使用指针参数
func swapPtr(a, b *int) {
if a == b { // 避免同一个变量
return
}
*a = *a ^ *b
*b = *a ^ *b
*a = *a ^ *b
}
// 更安全的指针交换,防止溢出
func swapPtrArithmetic(a, b *int) {
if a == b {
return
}
*a = *a + *b
*b = *a - *b
*a = *a - *b
}
func main() {
x, y := 10, 20
fmt.Printf("交换前: x=%d, y=%d\n", x, y)
swapPtr(&x, &y)
fmt.Printf("交换后: x=%d, y=%d\n", x, y)
}
方法5:结构体方法交换
package main
import "fmt"
type Pair struct {
First, Second int
}
// 结构体方法:交换内部两个值
func (p *Pair) Swap() {
p.First ^= p.Second
p.Second ^= p.First
p.First ^= p.Second
}
// 交换两个结构体的值
func SwapPairs(p1, p2 *Pair) {
// 交换 First
p1.First ^= p2.First
p2.First ^= p1.First
p1.First ^= p2.First
// 交换 Second
p1.Second ^= p2.Second
p2.Second ^= p1.Second
p1.Second ^= p2.Second
}
func main() {
pair := &Pair{10, 20}
fmt.Printf("交换前: First=%d, Second=%d\n", pair.First, pair.Second)
pair.Swap()
fmt.Printf("交换后: First=%d, Second=%d\n", pair.First, pair.Second)
}
方法6:泛型实现(Go 1.18+)
package main
import "fmt"
// 泛型交换函数,仅支持整数类型
func SwapGeneric[T ~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64](a, b *T) {
if a == b {
return
}
*a ^= *b
*b ^= *a
*a ^= *b
}
// 使用泛型和约束
type Integer interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
func SwapGeneric2[T Integer](a, b *T) {
if a == b {
return
}
*a = *a + *b
*b = *a - *b
*a = *a - *b
}
func main() {
var x, y int = 10, 20
fmt.Printf("交换前: x=%d, y=%d\n", x, y)
SwapGeneric(&x, &y)
fmt.Printf("泛型交换后: x=%d, y=%d\n", x, y)
// 换回来
SwapGeneric2(&x, &y)
fmt.Printf("泛型交换2后: x=%d, y=%d\n", x, y)
}
方法7:匿名函数和闭包
package main
import "fmt"
func main() {
a, b := 10, 20
fmt.Printf("交换前: a=%d, b=%d\n", a, b)
// 使用匿名函数
swapFunc := func(x, y int) (int, int) {
x = x ^ y
y = x ^ y
x = x ^ y
return x, y
}
a, b = swapFunc(a, b)
fmt.Printf("匿名函数交换后: a=%d, b=%d\n", a, b)
// 或者立即执行的闭包
a, b = func(x, y int) (int, int) {
x = x + y
y = x - y
x = x - y
return x, y
}(a, b)
fmt.Printf("闭包交换后: a=%d, b=%d\n", a, b)
}
方法8:位运算的变种
package main
import "fmt"
// 使用不同的位运算组合
func swapBitsVariation(a, b int) (int, int) {
// 方法1: 标准异或
a = a ^ b
b = a ^ b
a = a ^ b
return a, b
}
// 另一种写法(单行表达式)
func swapOneLine(a, b int) (int, int) {
b = a ^ b ^ (a = b)
return a, b
}
func main() {
x, y := 10, 20
fmt.Printf("交换前: x=%d, y=%d\n", x, y)
x, y = swapOneLine(x, y)
fmt.Printf("单行交换后: x=%d, y=%d\n", x, y)
}
完整示例:性能比较
package main
import (
"fmt"
"time"
)
// 基准测试比较
func benchmarkSwap() {
const iterations = 100000000 // 1亿次
// 方法1: 元组赋值
start := time.Now()
a, b := 1, 2
for i := 0; i < iterations; i++ {
a, b = b, a
}
time1 := time.Since(start)
// 方法2: 异或运算
start = time.Now()
a, b = 1, 2
for i := 0; i < iterations; i++ {
a = a ^ b
b = a ^ b
a = a ^ b
}
time2 := time.Since(start)
// 方法3: 算术运算
start = time.Now()
a, b = 1, 2
for i := 0; i < iterations; i++ {
a = a + b
b = a - b
a = a - b
}
time3 := time.Since(start)
fmt.Printf("元组赋值: %v\n", time1)
fmt.Printf("异或运算: %v\n", time2)
fmt.Printf("算术运算: %v\n", time3)
}
func main() {
fmt.Println("性能比较 (1亿次交换):")
benchmarkSwap()
}
实际建议
- 生产代码:直接使用 a, b = b, a,这是最简洁、可读性最好的方式
- 面试题:如果需要展示不使用临时变量的方法,使用异或运算
- 注意事项:
· 算术方法可能溢出
· 异或方法对于同一变量会得到 0
· 乘除法方法要避免除零错误
// Go 中最推荐的交换方式
a, b := 10, 20
a, b = b, a // 简单明了,编译器会优化
Go 语言的元组赋值 a, b = b, a 在底层通常会被编译器优化,是性能最好且最安全的方式。
更多推荐

所有评论(0)