每日两题 T2
算法
LeetCode T945. 使数组唯一的最小增量[1]
描述
给定整数数组 A,每次 move 操作将会选择任意 A[i]
,并将其递增 1
。
返回使A
中的每个值都是唯一的最少操作次数。
示例 1:
输入:[1,2,2]
输出:1
解释:经过一次 move 操作,数组将变为 [1, 2, 3]。
示例 2:
输入:[3,2,1,2,1,7]
输出:6
解释:经过 6 次 move 操作,数组将变为 [3, 4, 1, 2, 5, 7]。
可以看出 5 次或 5 次以下的 move 操作是不能让数组的每个值唯一的。
提示:
1.0 <= A.length <= 40000
2.0 <= A[i] < 40000
分析
该问题有几种思路,我总结了两个:
一个是我们很容易想到的,将数组先排序,然后循环遍历,将当前元素与前一位置元素进行对比,若相等则+1,同时增加一次操作数。该方法比较简单,不做过多讲解,代码如下。
另外一种方式,我们想到在构建hash散列时,为了防止hash冲突,会通过一些算法来构建索引,其中一个方法就是线性探测法
,我们能完全将这个问题变相转化为解决散列hash值冲突问题,我们来看图文说明!
我们以 [3, 2, 1, 2, 1, 7]
,来模拟一遍线性探测的过程。
step1: 插入3:
因为3的位置是空的,所以直接放入3即可
step2: 插入2:
因为2的位置是空的,所以直接放入2即可
step3: 插入1:
因为1的位置是空的,所以直接放入1即可
step4: 插入2:
此时我们发现2的位置已经有值了,于是继续向后探测,直到找到空位4,于是2映射到了4。并且!!我们要对刚刚走过的路径2->3->4进行压缩,即将他们的值都设置为本次探测到的空位4
step5: 插入1:
此时我们发现1的位置已经有值了,于是向后探测,探测到了2,发现2的位置也有值了,但是由于2在上次的过程中存了上次的空位4,所以我们直接跳转到4+1即从5开始探测就行
step6: 插入7:
因为7的位置是空的,所以直接放入7即可
代码
/**
* @param {number[]} A
* @return {number}
*/
const pos = new Array(80000);
var minIncrementForUnique = function(A) {
pos.fill(-1); // -1表示空位
let move = 0;
// 遍历每个数字a对其寻地址得到位置b, b比a的增量就是操作数。
for (a of A) {
const b = findPos(a);
move += b - a;
}
return move;
};
function findPos(a) {
let b = pos[a];
// 如果a对应的位置pos[a]是空位,直接放入即可。
if (b == -1) {
pos[a] = a;
return a;
}
// 否则向后寻址
// 因为pos[a]中标记了上次寻址得到的空位,因此从pos[a]+1开始寻址就行了(不需要从a+1开始)。
b = findPos(b + 1);
pos[a] = b; // 寻址后的新空位要重新赋值给pos[a]哦,路径压缩就是体现在这里。
return b;
}
JavaScript
[1, 2, 3].map(parseInt)是多少?说明理由
首先考虑 map
方法的回调函数参数含义
arr.map(function callback(currentValue[, index[, array]]) { }
•currentValue 当前遍历的值•index 当前遍历索引•array 遍历数组
然后我们分析 parseInt
参数的含义
parseInt(string, radix)
•string 被处理的值•radix 基数即进制(2、8、10、16...进制)
当遍历到1时,map回调函数的参数分别为:1、0,即parseInt(1, 0),1的十进制数 为1
当遍历到2时,map回调函数的参数分别为:2、1,即parseInt(2, 1),1进制数为2的数不存在,即为 NaN
当遍历到3时,map回调函数的参数分别为:3、2,即parseInt(3, 2),2进制数为3的数不存在,即为 NaN
References
[1]
945. 使数组唯一的最小增量: https://leetcode-cn.com/problems/minimum-increment-to-make-array-unique/
- SpringBoot整合Mybatis之进门篇
- Tomcat和Java Virtual Machine的性能调优总结
- 一次浴火重生的MySQL优化(EXPLAIN命令详解)
- 简单聊聊不可或缺的Nginx反向代理服务器--实现负载均衡【上篇】
- Java设计模式之适配器设计模式(项目升级案例)
- Java设计模式之模板方法设计模式(银行计息案例)
- 多线程之策略模式
- 文件上传的动作不能太俗,必须页面无刷新上传
- 这次真的忽略了一些ActiveMQ内心的娇艳
- 多线程编程:阻塞、并发队列的使用总结
- 多线程编程:多线程并发制单的开发记录【一】
- 如何使用线程锁来提高多线程并发效率
- 如何在分布式环境中同步solr索引库和缓存信息
- 如何在分布式环境中同步solr索引库和缓存信息
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux下diff命令用法详解
- 详解Numpy中的数组拼接、合并操作
- 批量更改图像尺寸到统一大小
- 张东升,我知道是你!如何使用GAN做一个秃头生产器
- Roslyn 在 NuGet 包中放注释 xml 文件的方法
- OpenCV3 图像的加载、修改、显示与保存
- 打卡群刷题总结0727——搜索旋转排序数组 II
- dotnet 的 TaskCompletionSource 的 TrySetResult 是线程安全
- OpenCV 摄像头与视频读取并显示
- OpenCV 边缘检测
- Spring Boot 集成 WebSocket 实现服务端推送消息到客户端
- OpenCV 绘制图形
- OpenCV 图片缩放
- AI树莓派——构建树莓派大脑(NCNN环境搭建)
- PC人脸识别登录,出乎意料的简单