[Leedcode][JAVA]第[945]题

【问题描述】

给定整数数组 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 操作是不能让数组的每个值唯一的。
提示:0 <= A.length <= 40000
0 <= A[i] < 40000

【解答思路】

1. 排序 O(NlogN)

先排序,再依次遍历数组元素,若当前元素小于等于它前一个元素,则将其变为前一个数+1。

class Solution {public int minIncrementForUnique(int[] A) {// 先排序Arrays.sort(A);int move = 0;// 遍历数组,若当前元素小于等于它的前一个元素,则将其变为前一个数+1for (int i = 1; i < A.length; i++) {if (A[i] <= A[i - 1]) {int pre = A[i];A[i] = A[i - 1] + 1;move += A[i] - pre;}}return move;}}
2. 注意最后一个的推导 计数排序 O(N)
class Solution {public int minIncrementForUnique(int[] A) {// counter数组统计每个数字的个数。//(这里为了防止下面遍历counter的时候每次都走到40000,所以设置了一个max,这个数据量不设也行,再额外设置min也行)int[] counter = new int[40001];int max = -1;for (int num: A) {counter[num]++;max = Math.max(max, num);}// 遍历counter数组,若当前数字的个数cnt大于1个,则只留下1个,其他的cnt-1个后移int move = 0;for (int num = 0; num <= max; num++) {if (counter[num] > 1) {int d = counter[num] - 1;move += d;counter[num + 1] += d;}}// 最后, counter[max+1]里可能会有从counter[max]后移过来的,counter[max+1]里只留下1个,其它的d个后移。// 设 max+1 = x,那么后面的d个数就是[x+1,x+2,x+3,...,x+d],// 因此操作次数是[1,2,3,...,d],用求和公式求和。int d = counter[max + 1] - 1;move += (1 + d) * d / 2;return move;}
}
3. 线性探测法(含路径压缩) O(N) 神仙解法
  • 把原数组映射到一个地址不冲突的区域 ,和解决hash冲突的线性探测法比较相似
  • 直接线性探测可能会由于冲突导致反复探测耗时太长 -> 考虑探测的过程中进行路径压缩
  • 经过某条路径最终探测到一个空位置x后,将这条路径上的值都变成空位置所在的下标x,那么假如下次探测的点又是这条路径上的点,则可以直接跳转到这次探测到的空位置x,从x开始继续探测。

下面用样例2:[3, 2, 1, 2, 1, 7],来模拟一遍线性探测的过程。

模拟的过程中用int move来记录操作数(即要求的增量数)。

step1: 插入3:

image

因为3的位置是空的,所以直接放入3即可。(此时数组变成了上图,红色表示本次的更改)

move = 0 保持不变;

step2: 插入2:

image

因为2的位置是空的,所以直接放入2即可。(此时数组变成了上图,红色表示本次的更改)

move = 0 保持不变;

step3: 插入1:

image

因为1的位置是空的,所以直接放入1即可。(此时数组变成了上图,红色表示本次的更改)

move = 0 保持不变;

step4: 插入2:

image

此时我们发现2的位置已经有值了,于是继续向后探测,直到找到空位4,于是2映射到了4。

⚠️并且!!我们要对刚刚走过的路径2->3->4进行压缩,即将他们的值都设置为本次探测到的空位4(那么下次探测就可以直接从4往后找了~~)。

(此时数组变成了上图,红色表示本次的更改)

move = move + 4 - 2 = 2;

step5: 插入1:

image

此时我们发现1的位置已经有值了,于是向后探测,探测到了2,发现2的位置也有值了,但是由于2在上次的过程中存了上次的空位4,所以我们直接跳转到4+1即从5开始探测就行了(而不需要重复走一遍2->3->4这条路径喽!),此时我们发现5是个空位,因此将1映射到5,并且对刚刚走过的路径1->2->5进行路径压缩 即 使其都映射到5!

(此时数组变成了上图,红色表示本次的更改)

move = move + 5 - 1 = 6;

step6: 插入7:

image

因为7的位置是空的,所以直接放入7即可。(此时数组变成了上图,红色表示本次的更改)

move = 6 保持不变;

以上,最终move为6。

class Solution {int[] pos = new int [80000];public int minIncrementForUnique(int[] A) {Arrays.fill(pos, -1); // -1表示空位int move = 0;// 遍历每个数字a对其寻地址得到位置b, b比a的增量就是操作数。for (int a: A) {int b = findPos(a); move += b - a;}return move;}// 线性探测寻址(含路径压缩)private int findPos(int a) {int 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;}
}
4. 贪心算法 时间复杂度:O(Nlog N) 空间复杂度:O(1)
 public int minIncrementForUnique(int[] A) {int len = A.length;if (len == 0) {return 0;}Arrays.sort(A);// 打开调试// System.out.println(Arrays.toString(A));int preNum = A[0];int res = 0;for (int i = 1; i < len; i++) {// preNum + 1 表示当前数「最好」是这个值if (A[i] == preNum + 1) {preNum = A[i];} else if (A[i] > preNum + 1) {// 当前这个数已经足够大,这种情况可以合并到上一个分支preNum = A[i];} else {// A[i] < preNum + 1res += (preNum + 1 - A[i]);preNum++;}}return res;}

【总结】

  1. 思维过于局限 ,统计相同的数字分别+1,使用两层循环导致超时。
  2. 思维不跳跃,没有整体把握,第二种方法和第三种方法看了半天。

转载来自: https://leetcode-cn.com/problems/minimum-increment-to-make-array-unique/solution/ji-shu-onxian-xing-tan-ce-fa-onpai-xu-onlogn-yi-ya/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/426121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

玩转oracle 11g(37):rman备份-数据库指定文件恢复

.数据库指定数据文件恢复 启动数据库的时候报错 ORA-01157: cannot identify/lock data file 5 - see DBWR trace file ORA-01110: data file 5: D:\ORACLE\PRODUCT\10.2.0\ORADATA\DOCARE\AP MEDCOMM.DBF ORA-27041: unable to open file OSD-04002: 无法打开文件 O/S-Erro…

并发编程-concurrent指南-原子操作类-AtomicBoolean

类AtomicBoolean 可以用原子方式更新的 boolean 值。有关原子变量属性的描述&#xff0c;请参阅 java.util.concurrent.atomic 包规范。AtomicBoolean 可用在应用程序中&#xff08;如以原子方式更新的标志&#xff09;&#xff0c;但不能用于替换 Boolean。 2.构造函数 1.Atom…

[剑指offer]面试题第[7]题[JAVA][斐波那契数列][递归]

【问题描述】 大家都知道斐波那契数列&#xff0c;现在要求输入一个整数n&#xff0c;请你输出斐波那契数列的第n项&#xff08;从0开始&#xff0c;第0项为0&#xff09;。 n<39 【解答思路】 1.递归&#xff08;面试避免&#xff09; O(n^2) public class Solution {pu…

玩转oracle 11g(38):rman备份-全库恢复

(1)选择“开始” “运行”&#xff0c;输入cmd&#xff0c;按回车。 (2)输入“ set oracle_sidorcl”&#xff0c;按回车。 &#xff08;oracle_sid根据自己库的设置写&#xff09; (3)输入“rman target /”&#xff0c;按回车 (4)关闭数据库。输入“shutdown immediate;”…

Django补充

django页面渲染具体流程 在django的页面渲染中&#xff0c;下面这段程序 def test1(request):return render(request,aa.html,{data:wusir}) 等同于 from django.template import loader def test1(request):html loader.get_template(aa.html)html_str html.render({data:wu…

算法复杂度-BigO表示法

1.时间复杂度--大O表示法 算法的渐进时间复杂度&#xff0c;T(n)O(f(n)) T&#xff08;n&#xff09;表示算法的渐进时间复杂度 f&#xff08;n&#xff09;表示代码执行的次数 O&#xff08;&#xff09;表示正比例关系 2.常用的时间复杂度量级 3.举例 &#xff08;1&am…

玩转oracle 11g(40):Oracle11g 不区分大小写设定

Cmd>sqlplus / as sysdba Sql>show  parameter sec_case_sensitive_logon parameter sec_case_sensitive_logon的值为“true”说明区分大小写&#xff0c;为“false”说明不区分大小写&#xff0c;当为“true”时执行以下语句 ALTER SYSTEM SET SEC_CASE_SENSITIVE_…

[Leedcode][JAVA][第892题][图形题]

【问题描述】 在 N * N 的网格上&#xff0c;我们放置一些 1 * 1 * 1 的立方体。每个值 v grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。请你返回最终形体的表面积。示例 1&#xff1a;输入&#xff1a;[[2]] 输出&#xff1a;10 示例 2&#xff1a;输入&#xf…

hdu4554 A Famous Game 概率期望

题面 题意&#xff1a;n个球&#xff0c;2种颜色&#xff0c;可能有0~n个红球,每种情况的概率相同。现在从箱子里取出了$p$个球&#xff0c;其中有$Q$个是红球,问现在再取一个球是红球的概率为多少&#xff1f;题解&#xff1a;因为0 ~ n的概率相同&#xff0c;所以每个球是红色…

计算机论文搜索技巧【二】

##善用谷歌学术 ####本文以“blockchain”为例 1.创建快讯 当你确定了研究方向时&#xff0c;订阅功能会主动推送相关文章&#xff0c;是被动输入的神器 2.善用“左栏”筛选条件 3.善用文章摘要下“图标”扩展思路 如何下载文章 未完待续…

java学习(128):map类

定义一个汽车类 import java.util.Date; public class Car {private String brand;//品牌private Date createDate;private int housepower;//马力private int speed;//速度public void setBrand(String brand) {this.brand brand;}public String getBrand() {return brand;}…

java学习(129):hashmap的方法

import java.util.Date; public class Car {private String brand;//品牌private Date createDate;private int housepower;//马力private int speed;//速度public void setBrand(String brand) {this.brand brand;}public String getBrand() {return brand;}public Date getC…

java学习(130):treemap类

public class Department {private String code;//部门编号private String name;//部门名字private int quanity;//部门人员数量public void setCode(String code) {this.code code;}public String getCode() {return code;}public void setName(String name) {this.name nam…

[Leedcode][JAVA][第914题][最大公约数]

【问题描述】 给定一副牌&#xff0c;每张牌上都写着一个整数。此时&#xff0c;你需要选定一个数字 X&#xff0c;使我们可以将整副牌按下述规则分成 1 组或更多组&#xff1a;每组都有 X 张牌。 组内所有的牌上都写着相同的整数。 仅当你可选的 X > 2 时返回 true。示例 …

java学习(131):hashtable

import java.util.Hashtable;//hashtable public class test70 {public static void main(String[] args){Hashtable htnew Hashtable();ht.put("k0","歌谣");ht.put("k1","小白");ht.put("k2","小红");//ht.put…

如何快速在Github找到你想要的东西

众所周知 Github是全球最大的xx交友平台&#xff0c;虽然被收购了。但是不并没有什么影响。 使用Git可以做很多事&#xff0c;在这里不再缀述&#xff0c;上面的资源也是多种多样&#xff0c;应有尽有 对于这样一个平台&#xff0c;我们想快速找到自己需要的资源有什么好办法。…

[Leedcode][JAVA][第820题][字典树][Set]

【问题描述】 给定一个单词列表&#xff0c;我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。例如&#xff0c;如果这个列表是 ["time", "me", "bell"]&#xff0c;我们就可以将其表示为 S "time#bell#" 和 indexes [0, 2…

java学习(132):hashtable使用map替代实体数据

import java.util.*;public class test71 {public static void main(String[] args){Scanner innew Scanner(System.in);System.out.println("请输入学生的信息");List syuListnew ArrayList();//存储所有学生for(int i1;i<3;i){HashMap stuMapnew HashMap();Syst…

spring----06 更多DI知识

一. 延迟初始化 延迟初始化也叫做惰性初始化&#xff0c;指不提前初始化Bean&#xff0c;而是只有在真正使用时才创建及初始化Bean。配置方式很简单只需在<bean>标签上指定 “lazy-init” 属性值为“true”即可延迟初始化Bean Spring容器会在创建容器时提前初始化“singl…

[Leedcode][JAVA][第1162题][BFS]

【问题描述】 你现在手里有一份大小为 N x N 的『地图』&#xff08;网格&#xff09; grid&#xff0c;上面的每个『区域』&#xff08;单元格&#xff09;都用 0 和 1 标记好了。其中 0 代表海洋&#xff0c;1 代表陆地&#xff0c;你知道距离陆地区域最远的海洋区域是是哪一…