2026-04-04:最少翻转次数得到反转二进制字符串。用go语言,给定一个正整数 n。把 n 转成二进制字符串,记为 s(要求不带前导零)。
定义“反转字符串”:把 s 的所有字符顺序倒过来形成的新字符串,记为 rev(s)。
你可以在字符串 s 中选择任意一个位置,把该位置上的位进行翻转:把 0 改成 1,或把 1 改成 0。
每次翻转只改变一个位置上的字符。
目标:通过若干次这样的单点翻转,使得当前的二进制字符串恰好等于它自己的反转,也就是把 s 变成 rev(s)。
问:达到上述目标所需的最少翻转次数是多少。
1 <= n <= 1000000000。
输入: n = 10。
输出: 4。
解释:
10 的二进制表示为 "1010"。其反转为 "0101"。必须翻转所有四位才能使它们相等。因此,所需的最少翻转次数为 4。
题目来自力扣3750。
代码执行过程分步详细描述(以输入n=10为例)
我们先明确核心需求:将数字的二进制字符串变成回文(自身反转后和自己相同),求最少翻转0/1的次数,核心逻辑是:二进制原串和反转串对应位不同的数量,就是最少翻转次数。
下面分步骤拆解完整过程:
步骤1:接收输入的正整数
程序主函数中输入数字 10,将其传入计算函数 minimumFlips。
步骤2:将整数转换为无符号整数(方便位运算)
把输入的有符号整数 10 转换为无符号整数,目的是让Go语言的位运算工具能安全处理二进制位,避免符号位干扰。
- 输入数字:10
- 转换后无符号数:10(二进制无变化)
步骤3:获取数字的纯二进制字符串(无前置零)
数字10的标准二进制是 1010,这是核心处理的字符串,满足题目要求:不带前导零。
- 二进制长度:4位
- 二进制串:
1 0 1 0
步骤4:计算二进制串的反转字符串对应的数字
这一步是代码的核心操作:
- 先对原数字的所有二进制位进行完全反转(包含高位的0);
- 再剔除反转后多余的前导零,得到原二进制串反转后的纯数字。
- 原二进制串:
1010 - 反转后的二进制串:
0101(对应数字5)
步骤5:计算原二进制和反转二进制的异或结果
异或运算规则:相同位为0,不同位为1。这个运算能直接标记出「原串和反转串不一样的位置」。
- 原二进制:1 0 1 0
- 反转二进制:0 1 0 1
- 异或结果:1 1 1 1(所有位都不相同)
步骤6:统计异或结果中1的个数
异或结果里的每一个1,都代表需要翻转1次。统计1的数量,就是最少翻转次数。
- 异或结果:
1111 - 1的个数:4
- 最终结果:4
通用逻辑总结(所有数字都适用)
- 把输入数字转成无前置零的二进制字符串;
- 生成这个二进制串的反转字符串;
- 逐位对比原串和反转串,统计不相同的位的数量;
- 不相同的位的数量,就是最少需要翻转的次数。
时间复杂度 & 额外空间复杂度
1. 时间复杂度
代码中所有操作都是针对固定长度的二进制位(题目中n≤10亿,二进制最多30位):
- 位反转、剔除前导零、异或、统计1的个数,都是常数次操作;
- 与输入数字的大小无关。
总时间复杂度:O(1)(常数级)
2. 额外空间复杂度
程序执行过程中:
- 只定义了少量变量(存储原数、反转数、异或结果等);
- 没有使用数组、切片、哈希表等动态扩容的数据结构;
- 占用的内存空间固定,不随输入变化。
总额外空间复杂度:O(1)(常数级)
总结
- 核心逻辑:二进制原串和反转串的不同位数量 = 最少翻转次数;
- 执行效率:时间和空间都是常数级O(1),能高效处理题目要求的最大输入值。
Go完整代码如下:
package main
import (
"fmt"
"math/bits"
)
func minimumFlips(num int) int {
n := uint(num)
rev := bits.Reverse(n) >> bits.LeadingZeros(n)
return bits.OnesCount(n ^ rev)
}
func main() {
n := 10
result := minimumFlips(n)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def minimum_flips(num: int) -> int:
n = num
# Get binary representation without '0b' prefix
binary = bin(n)[2:]
bit_length = len(binary)
# Reverse the bits
rev = int(binary[::-1], 2)
# Count differing bits
return bin(n ^ rev).count('1')
def main():
n = 10
result = minimum_flips(n)
print(result)
if __name__ == "__main__":
main()
C++完整代码如下:
#include <iostream>
#include <bitset>
#include <algorithm>
#include <string>
int minimumFlips(int num) {
if (num == 0) return 1; // Special case: flipping 0 to itself? Actually returns 0
// Convert to binary string
std::string binary = std::bitset<32>(num).to_string();
// Trim leading zeros
binary = binary.substr(binary.find('1'));
// Reverse the string
std::string reversed = binary;
std::reverse(reversed.begin(), reversed.end());
// Convert back to integer
int rev_num = std::stoi(reversed, nullptr, 2);
// Count differing bits
int xor_result = num ^ rev_num;
return std::popcount(static_cast<unsigned int>(xor_result));
}
int main() {
int n = 10;
int result = minimumFlips(n);
std::cout << result << std::endl;
return 0;
}