【 每天学习一点算法 2026/05/26】计算右侧小于当前元素的个数

每天学习一点算法 2026/05/26

题目:计算右侧小于当前元素的个数

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: countsi 的值是 numsi 右侧小于 numsi 的元素的数量。

这题思路很简单,就是遍历数组 nums ,计算后续元素小于自身的个数。重点在于如何优化时间复杂度。

假如我们从右侧开始遍历,将已经遍历的元素进行降序排序,那么我们只需要在元素 nums[i] 右侧已排序的元素中找到第一个小于 nums[i] 的元素 nums[j] , nums[j] 及它后面的元素就都是小于 nums[i] 的,而且我们找到的位置 j 正是我们进行后续排序插入的 nums[i] 的位置,所以我们可以计算 count[i] 的同时进行排序操作。

由于实在排序数组中寻找元素,所以我们可以利用二分查找进一步进行优化。

typescript 复制代码
function countSmaller(nums: number[]): number[] {
  const len = nums.length
  if (len === 1) return [0] // 长度为 1 直接返回 [0]
  const counts = new Array(len).fill(0) // 结果数组
  const sortList: number[] = [nums[len - 1]] // 已排序部分
  // 从右往左遍历
  for (let i = len - 2; i >= 0; i--) {
    const j =  findSmaller(nums[i]) // 获取当前元素插入位置
    if (j === sortList.length) {
      // 如果插入位置在末尾,表示没有小于它的元素
      sortList.push(nums[i])
      counts[i] = 0
    } else {
      // 插入位置后的元素个数就是小于它的元素个数
      counts[i] = sortList.length - j
      sortList.splice(j, 0, nums[i])
    }
  }
  return counts
  // 辅助函数二分查找第一个小于目标的元素的位置 
  function findSmaller (target: number): number {
    let left = 0, right = sortList.length - 1
    let res = sortList.length
    while (left <= right) {
      const mid = Math.floor((left + right) / 2)
      if (target > sortList[mid]) {
        res = mid
        right = mid - 1
      } else {
        left = mid + 1
      }
    }
    return res
  }
};

我还纳闷这题怎么在树和图的题解里面,看了官方题解提到了树状数组,emmm 有点复杂。待我研究研究,明天写一篇 树状数组 的文章

题目来源:力扣(LeetCode)

相关推荐
CQU_JIAKE10 分钟前
9.28【A】
数据结构
Orange_sparkle15 分钟前
langgraph快速入门
学习·ai·typescript·deepseek·claude code
专注仿真8 小时前
ACM算法
算法·深度优先
差不多的周周9 小时前
《骨架上下文:基于零镜头骨架的动作识别的骨架侧上下文提示学习》论文核心部分详解
学习
code斗9 小时前
Java数据结构:堆详解
java·开发语言·数据结构
Century_Dragon10 小时前
从挂图到VR:汽修专业的一堂新能源原理课可以怎么上~
学习
知识分享小能手10 小时前
C++ 学习教程,从入门到精通,C++对象和类 — 详细知识点总结(10)
开发语言·c++·学习
顺顺 尼10 小时前
linux 进程信号(上)
linux·c++·算法
罗西的思考10 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 ---(5)--- GRPO
人工智能·算法·机器学习
richard_yuu11 小时前
动态规划:强化学习的「数学基础」,从 MDP 到值迭代
深度学习·神经网络·算法·yolo·机器学习·动态规划