2026-04-17:将数字变成二进制回文数的最少操作。用go语言,给你一个整数数组 nums。对数组里的每个位置 i,你都可以对 nums[i] 进行任意次“

0 阅读4分钟

2026-04-17:将数字变成二进制回文数的最少操作。用go语言,给你一个整数数组 nums。对数组里的每个位置 i,你都可以对 nums[i] 进行任意次“+1”或“-1”的调整(可以一次不做)。把某个整数改成“二进制回文数”(也就是它的二进制表示去掉前导零后,正着读和反着读完全相同),所需的最少调整次数是多少?把每个位置的最小次数依次放到结果数组 ans 中并返回,其中 ans[i] 表示把 nums[i] 变成二进制回文数的最小操作次数。

1 <= nums.length <= 5000。

1 <= nums[i] <= 5000。

输入:nums = [1,2,4]

输出:[0,1,1]

解释:

一种最优的操作集合如下:

nums[i]nums[i] 的二进制最近的回文数回文数的二进制所需操作ans[i]
1111已经是回文数0
210311加 11
4100311减 11

因此,ans = [0, 1, 1]。

题目来自力扣3766。

大体步骤

  1. 遍历输入的整数数组,逐个处理数组中的每一个数字,单独计算每个数字变成二进制回文数的最小操作次数。
  2. 对当前处理的数字,先获取它去除前导零后的二进制总位数,确定二进制回文数的构造规则:奇数位保留中间位,偶数位无中间位。
  3. 根据二进制总位数,拆分出二进制的左半部分数值,以该数值为中心,取前一个、本身、后一个三个候选值,用于构造回文数。
  4. 对每个候选左半部分,按照二进制回文规则生成完整的二进制回文数:将左半部分反转后拼接为右半部分,奇数位时保留中间位。
  5. 计算当前数字与每个构造出的二进制回文数的绝对差值,差值就是调整操作次数,记录最小的差值。
  6. 将每个数字对应的最小操作次数,按原数组顺序存入结果数组,所有数字处理完成后返回结果数组。

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

  1. 总时间复杂度:O(n),其中n是数组长度。数组每个元素仅进行固定次数的位运算、数值计算和比较,无嵌套循环,整体为线性时间复杂度。
  2. 总额外空间复杂度:O(1),仅使用了固定数量的临时变量存储中间结果,未开辟与输入规模相关的额外空间,结果数组属于题目要求的输出空间,不计入额外空间。

Go完整代码如下:

package main

import (
	"fmt"
	"math"
	"math/bits"
)

func minOperations(nums []int) []int {
	for i, x := range nums {
		res := math.MaxInt
		n := bits.Len(uint(x))
		m := n / 2
		left := x >> m
		for l := left - 1; l <= left+1; l++ {
			// 左半反转到右半
			// 如果 n 是奇数,先去掉正中间的比特,再反转
			right := bits.Reverse(uint(l>>(n%2))) >> (bits.UintSize - m)
			pal := l<<m | int(right)
			res = min(res, abs(x-pal))
		}
		nums[i] = res
	}
	return nums
}

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

func main() {
	nums := []int{1, 2, 4}
	result := minOperations(nums)
	fmt.Println(result)
}

在这里插入图片描述

Python完整代码如下:

# -*-coding:utf-8-*-

import math

def reverse_bits(v: int, width: int) -> int:
    """
    反转整数 v 的低 width 位,返回一个宽度为 width 的位反转结果。
    例如:v=6 (110b), width=3  -> 反转后为 011b = 3
    """
    res = 0
    for i in range(width):
        res = (res << 1) | ((v >> i) & 1)
    return res

def minOperations(nums):
    for i, x in enumerate(nums):
        res = math.inf
        n = x.bit_length()          # 相当于 bits.Len(uint(x))
        m = n // 2                   # 左半部分的位数
        left = x >> m                # 原始左半部分

        for delta in (-1, 0, 1):
            l = left + delta
            if l < 0:
                continue

            # 如果 n 是奇数,需要先去掉正中间的比特再反转
            to_reverse = l >> (n % 2)

            # 反转 to_reverse 的低 m 位,得到右半部分
            right = reverse_bits(to_reverse, m)

            # 拼接左半和右半,构造回文数
            pal = (l << m) | right
            res = min(res, abs(x - pal))

        nums[i] = res
    return nums

def main():
    nums = [1, 2, 4]
    result = minOperations(nums)
    print(result)  # 输出: [0, 1, 1]

if __name__ == "__main__":
    main()

在这里插入图片描述

C++完整代码如下:

#include <iostream>
#include <vector>
#include <climits>
#include <cmath>
#include <cstdint>

// 计算 x 的二进制位数(相当于 bits.Len)
int bitLen(uint32_t x) {
    if (x == 0) return 0;
    return 32 - __builtin_clz(x);  // GCC/Clang 内置函数
}

// 反转低 width 位(相当于 bits.Reverse 并右移对齐)
uint32_t reverseBits(uint32_t v, int width) {
    uint32_t res = 0;
    for (int i = 0; i < width; ++i) {
        res = (res << 1) | ((v >> i) & 1);
    }
    return res;
}

// 计算绝对值
int abs(int x) {
    return x < 0 ? -x : x;
}

std::vector<int> minOperations(std::vector<int>& nums) {
    for (int& x : nums) {
        int res = INT_MAX;
        uint32_t ux = static_cast<uint32_t>(x);
        int n = bitLen(ux);
        int m = n / 2;                      // 左半部分位数
        uint32_t left = ux >> m;            // 原始左半部分

        for (int delta = -1; delta <= 1; ++delta) {
            int l = static_cast<int>(left) + delta;
            if (l < 0) continue;

            uint32_t ul = static_cast<uint32_t>(l);
            // 若 n 为奇数,反转前先去掉正中间的比特(即右移 1 位)
            uint32_t toReverse = ul >> (n % 2);
            uint32_t right = reverseBits(toReverse, m);

            uint32_t pal = (ul << m) | right;
            int diff = abs(x - static_cast<int>(pal));
            if (diff < res) res = diff;
        }
        x = res;
    }
    return nums;
}

int main() {
    std::vector<int> nums = {1, 2, 4};
    std::vector<int> result = minOperations(nums);
    for (size_t i = 0; i < result.size(); ++i) {
        std::cout << result[i] << (i == result.size()-1 ? "\n" : ", ");
    }
    return 0;
}

在这里插入图片描述