目录

LC 1331. 数组序号转换 (opens new window) (opens new window)

简单

# 问题描述

给你一个整数数组 arr ,请你将数组中的每个元素替换为它们排序后的序号。

序号代表了一个元素有多大。序号编号的规则如下:

  • 序号从 1 开始编号。
  • 一个元素越大,那么序号越大。如果两个元素相等,那么它们的序号相同。
  • 每个数字的序号都应该尽可能地小。

示例 1:

输入:arr = [40,10,20,30]
输出:[4,1,2,3]
解释:40 是最大的元素。 10 是最小的元素。 20 是第二小的数字。 30 是第三小的数字。

示例 2:

输入:arr = [100,100,100]
输出:[1,1,1]
解释:所有元素有相同的序号。

示例 3:

输入:arr = [37,12,28,9,100,56,80,5,12]
输出:[5,3,4,2,8,6,7,1,3]

提示:

  • 0 <= arr.length <= 105
  • -109 <= arr[i] <= 109

# 哈希表

复制一份原数组进行排序,然后用一个哈希表保存首个出现元素的序号,最后遍历一次原数组,从哈希表中找出对应元素的序号。

/**
 * @param {number[]} arr
 * @return {number[]}
 */
var arrayRankTransform = function (arr) {
  const map = new Map()
  const order = Array.from(arr).sort((a, b) => a - b)
  for (let i = 0; i < order.length; i++) {
    if (!map.has(order[i])) map.set(order[i], map.size + 1)
  }
  const ans = new Array()
  for (let i = 0; i < arr.length; i++) {
    ans[i] = map.get(arr[i])
  }
  return ans
}
  • 时间复杂度:O(n×logn)O(n \times \log{n})nn 是输入数组的长度,排序消耗 O(n×logn)O(n \times \log{n}) 时间。
  • 空间复杂度:O(n)O(n)。有序数组和哈希表各消耗 O(n)O(n) 空间。

# 二分查找

复制一份原数组去重并排序,然后遍历原数组,利用二分查找找出该元素在排序后数组中的位置。

/**
 * @param {number[]} arr
 * @return {number[]}
 */
var arrayRankTransform = function (arr) {
  const order = Array.from(new Set(arr)).sort((a, b) => a - b)
  const ans = new Array(arr.length)
  for (let j = 0; j < arr.length; j++) {
    let l = 0
    let r = order.length - 1
    while (l < r) {
      const mid = (l + r) >> 1
      if (order[mid] === arr[j]) {
        l = mid
        break
      } else if (order[mid] < arr[j]) {
        l = mid + 1
      } else {
        r = mid
      }
    }
    ans[j] = l + 1
  }
  return ans
}
  • 时间复杂度:O(n×logn)O(n \times \log{n})nn 是输入数组的长度,排序和二分查找消耗 O(n×logn)O(n \times \log{n}) 时间,。
  • 空间复杂度:O(n)O(n)。有序数组消耗 O(n)O(n) 空间。
上次更新: 2023/01/31 19:48:05

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 , 转载请注明出处!