2026-04-04:最少翻转次数得到反转二进制字符串。用go语言,给定一个正整数 n。把 n 转成二进制字符串,记为 s(要求不带前导零)。 定义“反转字符串

0 阅读5分钟

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:计算二进制串的反转字符串对应的数字

这一步是代码的核心操作:

  1. 先对原数字的所有二进制位进行完全反转(包含高位的0);
  2. 再剔除反转后多余的前导零,得到原二进制串反转后的纯数字
  • 原二进制串: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. 把输入数字转成无前置零的二进制字符串
  2. 生成这个二进制串的反转字符串
  3. 逐位对比原串和反转串,统计不相同的位的数量
  4. 不相同的位的数量,就是最少需要翻转的次数。

时间复杂度 & 额外空间复杂度

1. 时间复杂度

代码中所有操作都是针对固定长度的二进制位(题目中n≤10亿,二进制最多30位):

  • 位反转、剔除前导零、异或、统计1的个数,都是常数次操作
  • 与输入数字的大小无关。

总时间复杂度:O(1)(常数级)

2. 额外空间复杂度

程序执行过程中:

  • 只定义了少量变量(存储原数、反转数、异或结果等);
  • 没有使用数组、切片、哈希表等动态扩容的数据结构;
  • 占用的内存空间固定,不随输入变化。

总额外空间复杂度:O(1)(常数级)

总结

  1. 核心逻辑:二进制原串和反转串的不同位数量 = 最少翻转次数
  2. 执行效率:时间和空间都是常数级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;
}

在这里插入图片描述