**数组按二进制比特排序**

2026 华为OD机试真题 6月17日华为OD上机新系统考试真题 200 分题型

点击查看华为 OD 机试真题完整目录:2026最新华为OD机试新系统卷 + 双机位C卷 真题题库目录|全覆盖题库 + 逐点算法考点详解

题目描述

给定两个 int 数组,数据数组(一维)和操作数组(二维):

  • 数据数组:存放待操作的整数;
  • 操作数组:每个元素为包含两个 int 的一维数组,这两个 int 数字指定当前需要操作的数据数组下标(从 0 开始)。

2026 华为OD机试真题 6月17日华为OD上机新系统考试真题 200 分题型

操作流程

  1. 对数据数组排序:按整数二进制表示中 1 的个数升序排列(符号位中的 1 也计入);1 的个数相同时,按数值升序排列。
  2. 依次对操作数组中的每个元素执行以下操作: 2.1 读取两个下标,取当前数据数组中对应位置的元素,计算它们的二进制按位或,将结果追加到数据数组末尾,并删除原来的两个元素(元素下标允许相同,此时仅删除一个元素)。 2.2 对更新后的数据数组按步骤 1 的规则重新排序。
  3. 输出最终排序后的数据数组。

注意

  • 数据数组的长度范围为 [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. 自定义排序规则

    • 首先统计每个整数的二进制表示中 1 的个数(也称为 popcount 或汉明重量)。
    • 排序规则:第一关键字是 popcount 升序;第二关键字是数值本身升序。
    • 由于负数的二进制表示比较特殊(采用补码),我们需要将其与 32 位无符号整数范围 [0, 2^32-1] 对应起来进行 popcount 统计。具体做法是将负数与 0xFFFFFFFF 进行按位与操作后再统计。
  2. 模拟合并操作

    • 对于每一对下标 (i, j),取出对应元素 ab
    • 如果下标相同,则 b 等于 a(只取一个元素)。
    • 计算合并结果 result = a | b(按位或)。
    • 从数组中删除被选中的元素。注意:由于删除元素会导致后续下标偏移,需要先删除下标较大的元素,再删除下标较小的元素
    • 将合并结果 result 添加到数组末尾。
    • 再次对数组应用排序规则。
  3. 输入输出处理

    • 输入格式为两个数组:数据数组操作数组
    • 数据数组直接解析为整数列表。
    • 操作数组解析为包含两个整数的列表的列表。
    • 输出格式为数组的字符串表示,例如 [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),主要用于存储数组和辅助
THE END