kth


CST PA4

4-3 Kth

算法构思

因为不能直接访问数组 a, b, c 中的元素, 我们定义数组 u, v, w, 将其初始化为 $\{1, 2, …, n\}$, 用于记录数组 a, b, c 中元素的 index.

将三元组视为三维空间中的点集, 我们需要返回点集之中坐标和第 k 小的三元组. 在 compare 接口中固定两维度 index1, 我们可以比较单一维度的元素大小. 借此对三个数组分别进行快排, 排序结果反应在数组 u, v, w 中.

一般地, 若排序前数组 u 为 $\{1, 2, …, n\}$, 排序后为 $\{u[1], u[2], …, u[n]\}$, 即意味着数组 a 元素按大小升序排列为 $\{a[u[1]], a[u[2]], …, a[u[n]]\}$.

此时点集中坐标和最小的三元组即为 $a[u[1]], b[v[1]], c[w[1]]$. 我们维护一个最小堆 MinHeap, 将 $(1, 1, 1)$ 插入. 随后依次删除堆顶最小元组, 并插入坐标和恰好不小于删去堆顶坐标和的三元组.

kDelete 得到的三元组 $(x, y, z)$ 对应的即是坐标和第 k 小的三元组 $a[u[x]], b[v[y]], c[w[z]]$.

对这个三维点集, 坐标和恰不小于 $(x, y, z)$ 的三元组必是 $(x, y, z + 1)$, $(x, y + 1, z)$, $(x + 1, y, z)$ 之一, 将其插入 MinHeap 即可. 考虑到同一个点可能会被压入多次, 调用 kDelete() 后得到不是坐标和第 k 小的三元组, 特约定:

对于堆顶三元组 $(x, y, z)$, 我们插入 $(x, y, z + 1)$; 若 $z = 1$, 再插入 $(x, y + 1, z)$; 若 $y = z = 1$, 再插入 $(x + 1, y, z)$.

问题解决

  • 在每次插入 $(x, y, z)$ 应该检查坐标是否合理, 否则会因非法插入, 使得 compare 函数报错.

复杂度估计

时间复杂度

对数组 a, b, c 进行快速排序, 时间复杂度为 $O(nlogn)$;

在维护 MinHeap 的过程中, 进行 kDelete, 至多进行 3kInsert, 时间复杂度为 $O(klogk)$.

综上, 算法总体时间复杂度为 $O(nlogn + klogk)$.

空间复杂度

数组 u, v, w 动态分配的空间为 $O(n)$, 堆 MinHeap 消耗的空间为 $O(k)$, 因此算法总体空间复杂度为 $O(n + k)$.

本题中直接在堆内开辟了相关大小的数组存储信息,

// Line 13
class MinHeap { // 实现一个三元之和最小堆.
    ...
private:
    int elem[4000100][3];
    int size = 0;
};

空间消耗最坏情况约为: $3\times 5\times 10^5 \times 4B + 1.2\times 10^7 \times 4B = 52MB < 256MB$, 符合题目要求范围.


文章作者: Chengsx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Chengsx !
  目录