**数组按二进制比特排序**
2026 华为OD机试真题 6月17日华为OD上机新系统考试真题 200 分题型
点击查看华为 OD 机试真题完整目录:2026最新华为OD机试新系统卷 + 双机位C卷 真题题库目录|全覆盖题库 + 逐点算法考点详解
题目描述
给定两个 int 数组,数据数组(一维)和操作数组(二维):
- 数据数组:存放待操作的整数;
- 操作数组:每个元素为包含两个 int 的一维数组,这两个 int 数字指定当前需要操作的数据数组下标(从 0 开始)。
2026 华为OD机试真题 6月17日华为OD上机新系统考试真题 200 分题型
操作流程
- 对数据数组排序:按整数二进制表示中 1 的个数升序排列(符号位中的 1 也计入);1 的个数相同时,按数值升序排列。
- 依次对操作数组中的每个元素执行以下操作: 2.1 读取两个下标,取当前数据数组中对应位置的元素,计算它们的二进制按位或,将结果追加到数据数组末尾,并删除原来的两个元素(元素下标允许相同,此时仅删除一个元素)。 2.2 对更新后的数据数组按步骤 1 的规则重新排序。
- 输出最终排序后的数据数组。
注意
- 数据数组的长度范围为 [0,100],元素值范围为 [−231,231−1]。
- 操作数组的长度范围为 [0,10],每个元素中数组长度保证为 2,数值作为当前数据数组下标保证不会越界。
- 即使操作数组为空,最后输出的数据数组也需要按照描述的排序方式输出有序数据数组。
输入描述
两个 int 数组,数据数组(一维)和操作数组(二维)
输出描述
最终排序后的数据数组
示例1
输入
[3,2,1],[[0,1]]
输出
[3,3]
说明
排序后内容为 [1,2,3],对 1 和 2 进行或操作得到 3,删除并插入重新排序后得到 [3,3]。
示例2
输入
[1024,512,256,128,64,32,16,8,4,2,1,0,-1],[[0,1],[0,1],[0,1],[1,2]]
输出
[16,128,256,512,1024,3,12,96,-1]
说明
排序后内容为 [0,1,2,4,8,16,32,64,128,256,512,1024,−1],经过第一次操作结果为 [0,1,2,4,8,16,32,64,128,256,512,1024,−1],第二次操作结果为 [4,8,16,32,64,128,256,512,1024,3,1024,−1],第三次操作结果为 [16,32,64,128,256,512,1024,3,12,−1],最后一次操作结果为 [16,128,256,512,1024,3,12,96,−1]。
示例3
输入
[2147483647,-2147483648,-1,0],[[1,2],[2,2]]
输出
[0,-1,-1]
说明
原始数组按照二进制表示为[01111111111111111111111111111111,10000000000000000000000000000000,11111111111111111111111111111111,00000000000000000000000000000000],按照 1 的数量进行排序后数组顺序为: [0,−2147483648,2147483647,−1]。
接下来对 index 为 1 和 2 的元素即 −2147483648、2147483647 进行或操作获得结果 −1,将 [−2147483648,2147483647] 从数组中删除并插入 −1 后得到 [0,−1,−1]。
最后对 index 为 2 的元素自身进行或操作不会改变数据。最终返回 [0,−1,−1]。
解题思路
本题的核心在于按二进制中 1 的个数进行稳定排序,并模拟一个不断合并元素的动态过程。
关键算法点
-
自定义排序规则:
- 首先统计每个整数的二进制表示中
1的个数(也称为 popcount 或汉明重量)。 - 排序规则:第一关键字是 popcount 升序;第二关键字是数值本身升序。
- 由于负数的二进制表示比较特殊(采用补码),我们需要将其与 32 位无符号整数范围
[0, 2^32-1]对应起来进行 popcount 统计。具体做法是将负数与0xFFFFFFFF进行按位与操作后再统计。
- 首先统计每个整数的二进制表示中
-
模拟合并操作:
- 对于每一对下标
(i, j),取出对应元素a和b。 - 如果下标相同,则
b等于a(只取一个元素)。 - 计算合并结果
result = a | b(按位或)。 - 从数组中删除被选中的元素。注意:由于删除元素会导致后续下标偏移,需要先删除下标较大的元素,再删除下标较小的元素。
- 将合并结果
result添加到数组末尾。 - 再次对数组应用排序规则。
- 对于每一对下标
-
输入输出处理:
- 输入格式为两个数组:
数据数组和操作数组。 - 数据数组直接解析为整数列表。
- 操作数组解析为包含两个整数的列表的列表。
- 输出格式为数组的字符串表示,例如
[1,2,3]。
- 输入格式为两个数组:
边界情况处理
- 空数组:即使数据数组为空,输出也应为
[]。 - 空操作列表:即使没有操作,也需要输出排序后的数组。
- 相同下标操作:此时只删除一个元素,合并结果即为该元素自身按位或(不变)。
- 32 位边界值:需要正确处理
Integer.MAX_VALUE(2147483647) 和Integer.MIN_VALUE(-2147483648) 的 popcount 计算。
复杂度分析
- 时间复杂度:设数据数组长度为
n,操作数组长度为m。- 每次排序的时间复杂度为
O(n log n)。 - 总共进行
m + 1次排序(初始一次 + 每次操作后一次)。 - 极端情况下总时间复杂度为
O((n + m) * n log n),但由于n <= 100, m <= 10,该复杂度完全在可接受范围内。
- 每次排序的时间复杂度为
- 空间复杂度:
O(n),主要用于存储数组和辅助