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

题目链接

315. 计算右侧小于当前元素的个数 - 力扣(LeetCode)

题解

前置概念:

  • in 和 of 区别

in 操作符:遍历或者检查对象的键名,遍历的是可枚举属性名,不适合遍历数组,会遍历原型链上的属性

of 操作符:遍历可迭代对象的键值(数组,字符串,Map,Set 等,不能遍历普通对象,除非定义了 Symbol.iterotor)不会遍历原型链

  • size 和 length 区别

length 适合用于类数组 (数组,字符串),表示索引的个数

size 用于集合类型,表示键值对/元素的个数

  • lowBit 函数

作用是 只保留一个整数的二进制中最右边的1,并将其余位置全部为0

利用了计算机中负数以补码的形式存储的特性

为什么 x & (-x) 能留下最右边的 1?

  1. 对于 x 的最右边的 1,设它在第 k 位

  2. 这个 1 右边的所有位都是 0

  3. 当对 x 取反时,第 k 位变成 0,右边的 0 都变成 1

  4. 再加 1 时,进位会把第 k 位重新变成 1,而右边又变回 0

  5. 这样,-x 的第 k 位也是 1,且第 k 位右边的位都是 0

  6. 所以 x & (-x) 的结果中,只有第 k 位是 1

  • 树状数组:

树状数组详解

思路:

先排序然后构建一个树状数组,从后往前开始计算遍历构建一个树状数组,根据当前的 numsi 缓存下标到 map 里面(没用二分查找是因为时间超限,使用这个是以空间换时间,事件复杂度从logn 到 1),最后输出倒序的结果即可

代码

javascript 复制代码
var countSmaller = function(nums) {
    let c = [];
    let a = [];
    let valueToIndex = new Map();

    function init(length) {
        return new Array(length + 5).fill(0);
    }

    function lowBit(x) {
        return x & (-x);
    }

    function update(pos) {
        while (pos < c.length) {
            c[pos]++;
            pos += lowBit(pos);
        }
    }

    function query(pos) {
        let resNum = 0;
        while (pos > 0) {
            resNum += c[pos];
            pos -= lowBit(pos);
        }
        return resNum;
    }

    function discretization(nums) {
        // 去重并排序
        let set = new Set(nums);
        a = Array.from(set).sort((x, y) => x - y);
        
        // 建立映射(索引从1开始)
        a.forEach((val, idx) => {
            valueToIndex.set(val, idx + 1);
        });
    }

    function getRes() {
        let res = [];
        discretization(nums);
        c = init(nums.length);
        
        for (let i = nums.length - 1; i >= 0; i--) {
            let id = valueToIndex.get(nums[i]); // O(1) 获取
            res.push(query(id - 1)); // 查询比它小的个数
            update(id); // 把自己加进去
        }
        
        return res.reverse();
    }

    return getRes();
};
相关推荐
默_笙1 小时前
🎃 前端学了 Next.js,后端该学啥?NestJS 就是 Node 版的蜜雪冰城
前端·javascript
晊晌_h1 小时前
嵌入式从0到精通——数据结构总结[特殊字符]
数据结构·算法·排序算法
我找到地球的支点啦2 小时前
Matlab系列(009) 一CRC循环冗余校验详解
开发语言·数据结构·算法·matlab·信息与通信
罗西的思考2 小时前
【OpenClaw具身硬件】ZeroClaw 源码阅读笔记(3)--- RAG
人工智能·算法·机器学习
এ慕ོ冬℘゜2 小时前
navigator 导航对象 BOM制作方法
javascript
浪里镖客3 小时前
位姿转换矩阵写法-个人习惯(计算机理解其实是相反的)
线性代数·算法·矩阵
kyriewen5 小时前
面试官让我用 AI 重构一个 8 年陈的 React 组件——他说他不看代码,只看我会不会拆
前端·javascript·面试
Jacky19996 小时前
Electron + Vue 3 桌面打字游戏实战:从 VSCode 扩展到独立应用的架构改造
javascript
小白羊丨6 小时前
如何诊断 Prompt 模板导致的效果下降?
人工智能·算法·prompt
OPEN-F7 小时前
C++11/14新特性精讲:移动语义与智能指针实战
开发语言·c++·算法