LeetCode:LCP 24. 数字游戏(对顶堆求中位数 Java)

2024-02-02 21:28

本文主要是介绍LeetCode:LCP 24. 数字游戏(对顶堆求中位数 Java),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

LCP 24. 数字游戏

题目描述:

实现代码与解析:

原理思路:


LCP 24. 数字游戏

题目描述:

        小扣在秋日市集入口处发现了一个数字游戏。主办方共有 N 个计数器,计数器编号为 0 ~ N-1。每个计数器上分别显示了一个数字,小扣按计数器编号升序将所显示的数字记于数组 nums。每个计数器上有两个按钮,分别可以实现将显示数字加一或减一。小扣每一次操作可以选择一个计数器,按下加一或减一按钮。

主办方请小扣回答出一个长度为 N 的数组,第 i 个元素(0 <= i < N)表示将 0~i 号计数器 初始 所示数字操作成满足所有条件 nums[a]+1 == nums[a+1],(0 <= a < i) 的最小操作数。回答正确方可进入秋日市集。

由于答案可能很大,请将每个最小操作数对 1,000,000,007 取余。

示例 1:

输入:nums = [3,4,5,1,6,7]

输出:[0,0,0,5,6,7]

解释: i = 0,[3] 无需操作 i = 1,[3,4] 无需操作; i = 2,[3,4,5] 无需操作; i = 3,将 [3,4,5,1] 操作成 [3,4,5,6], 最少 5 次操作; i = 4,将 [3,4,5,1,6] 操作成 [3,4,5,6,7], 最少 6 次操作; i = 5,将 [3,4,5,1,6,7] 操作成 [3,4,5,6,7,8],最少 7 次操作; 返回 [0,0,0,5,6,7]。

示例 2:

输入:nums = [1,2,3,4,5]

输出:[0,0,0,0,0]

解释:对于任意计数器编号 i 都无需操作。

示例 3:

输入:nums = [1,1,1,2,3,4]

输出:[0,1,2,3,3,3]

解释: i = 0,无需操作; i = 1,将 [1,1] 操作成 [1,2] 或 [0,1] 最少 1 次操作; i = 2,将 [1,1,1] 操作成 [1,2,3] 或 [0,1,2],最少 2 次操作; i = 3,将 [1,1,1,2] 操作成 [1,2,3,4] 或 [0,1,2,3],最少 3 次操作; i = 4,将 [1,1,1,2,3] 操作成 [-1,0,1,2,3],最少 3 次操作; i = 5,将 [1,1,1,2,3,4] 操作成 [-1,0,1,2,3,4],最少 3 次操作; 返回 [0,1,2,3,3,3]。

实现代码与解析:

对顶堆求中位数

class Solution {public int[] numsGame(int[] nums) {final int MOD = 1000000007;PriorityQueue<Integer> lq = new PriorityQueue<>((a, b) -> b - a); // 大根堆PriorityQueue<Integer> rq = new PriorityQueue<>(); // 小根堆int n = nums.length;int[] res = new int[n];long lsum = 0;long rsum = 0;for (int i = 0; i < n; i++) {int t = nums[i] - i;if (i % 2 == 0) {lq.offer(t);lsum += t;int j = lq.peek();lq.poll();lsum -= j;rq.offer(j);rsum += j;res[i] = (int) ((rsum - rq.peek() - lsum) % MOD);} else {rq.offer(t);rsum += t;int j = rq.peek();rq.poll();rsum -= j;lq.offer(j);lsum += j;res[i] =  res[i] = (int) ((rsum - lsum) % MOD);}}  return res;}
}

原理思路:

        题目转化:就是所有nums[i] - i 变成相同值的最小和,而这个相同值就是他们的中位数,把这些数放在数轴上就可以很好的观察出来,也可以作为定理记下来。  

        至于为啥是num[i] - i,可以简单证明一下。例如有一个值 a0, a1, a2,假设最后结果为b , b + 1, b + 2,那么和就为|a0 - (b + 0)| + |a1 - (b + 1)| + |a2 - (b + 2)| 等价于sum|(ai - i - b)|,把ai - i 看成一个整体ti,那么就变成了每一个 ti 到某一个值的距离最小和。这个值就是中位数。  

        所以这题的核心就是求中位数,如何求?

就是对顶堆(双优先级队列lq,rq)

- 中位数左的小数用lq大顶堆维护  

- 中位数右的大数用rq小顶堆维护  

- x 为我们正在遍历的数  

- 如果前缀长度是奇数,此时 lq 和 rq 大小相等,我们先把 x 插入 lq,然后弹出 lq 的堆顶,加到 rq 中。这一操作可以保证,无论 x 是大是小,此时 rq 的堆顶就是中位数。  

- 如果前缀长度是偶数,此时 lq 比 rq 少一个元素,我们先把 x 插入 rq,然后弹出 rq 的堆顶,加到 lq 中。

        当然这里是可以优化的,比如奇数时,lq里的最大值都小于x,那么就直接放进rq就好了,就省去了进lq,再出来进rq的步骤,偶数时同理。

        这题只要想到题目转换的含义就很好写了。

这篇关于LeetCode:LCP 24. 数字游戏(对顶堆求中位数 Java)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/672007

相关文章

Spring实现Bean的初始化和销毁的方式

《Spring实现Bean的初始化和销毁的方式》:本文主要介绍Spring实现Bean的初始化和销毁的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Bean的初始化二、Bean的销毁总结在前面的章节当中介绍完毕了ApplicationContext,也就

Java的"伪泛型"变"真泛型"后对性能的影响

《Java的伪泛型变真泛型后对性能的影响》泛型擦除本质上就是擦除与泛型相关的一切信息,例如参数化类型、类型变量等,Javac还将在需要时进行类型检查及强制类型转换,甚至在必要时会合成桥方法,这篇文章主... 目录1、真假泛型2、性能影响泛型存在于Java源代码中,在编译为字节码文件之前都会进行泛型擦除(ty

Java中的getBytes()方法使用详解

《Java中的getBytes()方法使用详解》:本文主要介绍Java中getBytes()方法使用的相关资料,getBytes()方法有多个重载形式,可以根据需要指定字符集来进行转换,文中通过代... 目录前言一、常见重载形式二、示例代码三、getBytes(Charset charset)和getByt

Java使用Stream流的Lambda语法进行List转Map的操作方式

《Java使用Stream流的Lambda语法进行List转Map的操作方式》:本文主要介绍Java使用Stream流的Lambda语法进行List转Map的操作方式,具有很好的参考价值,希望对大... 目录背景Stream流的Lambda语法应用实例1、定义要操作的UserDto2、ListChina编程转成M

Spring框架中@Lazy延迟加载原理和使用详解

《Spring框架中@Lazy延迟加载原理和使用详解》:本文主要介绍Spring框架中@Lazy延迟加载原理和使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、@Lazy延迟加载原理1.延迟加载原理1.1 @Lazy三种配置方法1.2 @Component

使用easy connect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题

《使用easyconnect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题》:本文主要介绍使用easyconnect之后,maven无法... 目录使用easGWowCy connect之后,maven无法使用,原来需要配置-DJava.net.pr

idea报错java: 非法字符: ‘\ufeff‘的解决步骤以及说明

《idea报错java:非法字符:‘ufeff‘的解决步骤以及说明》:本文主要介绍idea报错java:非法字符:ufeff的解决步骤以及说明,文章详细解释了为什么在Java中会出现uf... 目录BOM是什么?1. BOM的作用2. 为什么会出现 \ufeff 错误?3. 如何解决 \ufeff 问题?最

使用Java编写一个字符脱敏工具类

《使用Java编写一个字符脱敏工具类》这篇文章主要为大家详细介绍了如何使用Java编写一个字符脱敏工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、字符脱敏工具类2、测试工具类3、测试结果1、字符脱敏工具类import lombok.extern.slf4j.Slf4j

Java实现按字节长度截取字符串

《Java实现按字节长度截取字符串》在Java中,由于字符串可能包含多字节字符,直接按字节长度截取可能会导致乱码或截取不准确的问题,下面我们就来看看几种按字节长度截取字符串的方法吧... 目录方法一:使用String的getBytes方法方法二:指定字符编码处理方法三:更精确的字符编码处理使用示例注意事项方

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约