2026-04-20:二进制反射排序。用go语言,把数组里每个数先转成二进制;对它的二进制表示做“二进制反射”(把二进制位从左到右反过来,前导零不计入);再把反射后的二进制串转回十进制,这个结果就是该元素的“反射值”。
然后按所有元素的反射值从小到大排序;若两个数的反射值相同,则比较它们原始的数值大小,原数更小的排在前面。
最后返回排序后的数组。
1 <= nums.length <= 100。
1 <= nums[i] <= 1000000000。
输入: nums = [3,6,5,8]。
输出: [8,3,6,5]。
解释:
二进制反射值为:
3 -> (二进制) 11 -> (反转) 11 -> 3
6 -> (二进制) 110 -> (反转) 011 -> 3
5 -> (二进制) 101 -> (反转) 101 -> 5
8 -> (二进制) 1000 -> (反转) 0001 -> 1
根据反射值排序为 [8, 3, 6, 5]。
注意,3 和 6 的反射值相同,因此需要按原始值的升序排列。
题目来自力扣3769。
二进制反射排序完整过程详解
第一步:明确核心定义
- 二进制转换:把每个十进制数字转为无前导零的二进制字符串
- 二进制反射:将二进制字符串整体反转,忽略反转后产生的前导零,再转回十进制,得到反射值
- 排序规则:
- 优先按反射值从小到大排序
- 反射值相同时,按原始数值从小到大排序
第二步:逐个计算每个数字的反射值
我们对数组 [3, 6, 5, 8] 中的每个元素,依次计算反射值:
1. 数字 3
- 十进制 → 二进制(无前导零):
11 - 二进制反射(反转):
11 - 反转后转回十进制:
3 - 反射值 = 3,原始值 = 3
2. 数字 6
- 十进制 → 二进制(无前导零):
110 - 二进制反射(反转):
011(忽略前导零 →11) - 反转后转回十进制:
3 - 反射值 = 3,原始值 = 6
3. 数字 5
- 十进制 → 二进制(无前导零):
101 - 二进制反射(反转):
101 - 反转后转回十进制:
5 - 反射值 = 5,原始值 = 5
4. 数字 8
- 十进制 → 二进制(无前导零):
1000 - 二进制反射(反转):
0001(忽略前导零 →1) - 反转后转回十进制:
1 - 反射值 = 1,原始值 = 8
第三步:整理所有元素的「反射值+原始值」
整理后结果:
- 8:反射值 1,原始值 8
- 3:反射值 3,原始值 3
- 6:反射值 3,原始值 6
- 5:反射值 5,原始值 5
第四步:按照排序规则排序
-
第一优先级:反射值升序 反射值大小:
1 < 3 < 5所以 8(1)排第一,5(5)排最后;3 和 6 反射值都是 3,并列中间。 -
第二优先级:反射值相同时,原始值升序 3 和 6 反射值相同,原始值
3 < 6,所以 3 排在 6 前面。
第五步:得到最终结果
排序后数组:[8, 3, 6, 5]
时间复杂度 & 额外空间复杂度分析
1. 时间复杂度
- 核心操作是自定义排序,Go 语言
slices.SortFunc底层使用快速排序/优化排序,时间复杂度为 O(n log n)(n 是数组长度)。 - 排序过程中,每个元素会计算一次反射值,计算反射值是固定位数的二进制操作(常数时间 O(1))。
- 总时间复杂度:O(n log n)。
2. 额外空间复杂度
- 代码直接在原数组上进行排序,没有创建新的数组存储数据。
- 排序和计算反射值仅使用了常数个临时变量。
- 总额外空间复杂度:O(1)(原地操作,常数空间)。
总结
- 完整执行流程:计算每个数的二进制→二进制反转→计算反射值→按反射值排序→反射值相同按原数排序→输出结果
- 时间复杂度:O(n log n)
- 额外空间复杂度:O(1)(原地排序,无额外数组开销)
Go完整代码如下:
package main
import (
"cmp"
"fmt"
"math/bits"
"slices"
)
func sortByReflection(nums []int) []int {
slices.SortFunc(nums, func(a, b int) int {
revA := int(bits.Reverse(uint(a)) >> bits.LeadingZeros(uint(a)))
revB := int(bits.Reverse(uint(b)) >> bits.LeadingZeros(uint(b)))
return cmp.Or(revA-revB, a-b)
})
return nums
}
func main() {
nums := []int{3, 6, 5, 8}
result := sortByReflection(nums)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def sort_by_reflection(nums):
def reverse_bits(n):
# 将整数转换为二进制字符串,反转并去掉末尾的0
if n == 0:
return 0
# 获取二进制表示(去掉'0b'前缀)
binary = bin(n)[2:]
# 反转字符串
reversed_binary = binary[::-1]
# 转换为整数
return int(reversed_binary, 2)
def sort_key(num):
rev = reverse_bits(num)
# Python的排序是稳定的,我们通过返回元组来实现多级排序
return (rev, num)
# 使用sort()方法进行原地排序
nums.sort(key=sort_key)
return nums
def main():
nums = [3, 6, 5, 8]
result = sort_by_reflection(nums)
print(result)
if __name__ == "__main__":
main()
C++完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <bit>
#include <compare>
int reverseBits(int n) {
if (n == 0) return 0;
unsigned int u = static_cast<unsigned int>(n);
// C++23 提供 std::bit_reverse
// 如果编译器支持,可以使用:#if __cpp_lib_bit_reverse
// 否则使用手动实现
// 手动实现32位反转
u = ((u & 0x55555555) << 1) | ((u & 0xAAAAAAAA) >> 1);
u = ((u & 0x33333333) << 2) | ((u & 0xCCCCCCCC) >> 2);
u = ((u & 0x0F0F0F0F) << 4) | ((u & 0xF0F0F0F0) >> 4);
u = ((u & 0x00FF00FF) << 8) | ((u & 0xFF00FF00) >> 8);
u = (u << 16) | (u >> 16);
return static_cast<int>(u);
}
int leadingZeros(int n) {
if (n == 0) return 32;
return std::countl_zero(static_cast<unsigned int>(n));
}
std::vector<int> sortByReflection(std::vector<int>& nums) {
std::ranges::sort(nums, [](int a, int b) {
int revA = reverseBits(a) >> leadingZeros(a);
int revB = reverseBits(b) >> leadingZeros(b);
if (revA != revB) {
return revA < revB;
}
return a < b;
});
return nums;
}
int main() {
std::vector<int> nums = {3, 6, 5, 8};
std::vector<int> result = sortByReflection(nums);
for (size_t i = 0; i < result.size(); ++i) {
std::cout << result[i] << (i < result.size() - 1 ? ", " : "");
}
std::cout << std::endl;
return 0;
}