LeeCode 318周赛复盘
T1: 对数组执行操作
思路:模拟
public int[] applyOperations(int[] nums) {
int n = nums.length;
for (int i = 0; i < n - 1; ++i) {
if (nums[i] == nums[i + 1]) {
nums[i] = 2 * nums[i];
nums[i + 1] = 0;
}
}
int[] res = new int[n];
int index = 0;
for (int i = 0; i < n; i++) {
if (nums[i] != 0) {
res[index++] = nums[i];
}
}
return res;
}
T2: 长度为 K 子数组中的最大和
思路:滑动窗口
public long maximumSubarraySum(int[] nums, int k) {
int n = nums.length;
if (k > n) {
return 0;
}
// 哈希存储当前窗口内的数组元素
Map<Integer, Integer> map = new HashMap<>();
long res = 0;
long sum = 0;
int left = 0, right = 0;
while (right < n) {
sum += nums[right];
map.put(nums[right], map.getOrDefault(nums[right], 0) + 1);
if (right - left + 1 == k) {
if (map.size() == k) {
res = Math.max(res, sum);
}
sum -= nums[left];
map.put(nums[left], map.get(nums[left]) - 1);
if (map.get(nums[left]) == 0) {
map.remove(nums[left]);
}
left += 1;
}
right += 1;
}
return res;
}
T3: 雇佣 K 位工人的总代价
思路:小顶堆模拟
- 左堆堆顶元素 \(\le\) 右堆堆顶元素:弹出左堆值
- 左堆堆顶元素 \(\gt\) 右堆堆顶元素:弹出右堆值
public long totalCost(int[] costs, int k, int candidates) {
int n = costs.length;
long res = 0;
// 考虑特殊情况,快速返回结果
if (k == n) {
for (int cost : costs) {
res += cost;
}
return res;
}
if (candidates * 2 >= n) {
Queue<Integer> heap = new PriorityQueue<>();
for (int cost : costs) {
heap.offer(cost);
}
while (k > 0) {
res += heap.poll();
k -= 1;
}
return res;
}
// 小顶堆模拟
Queue<int[]> leftMin = new PriorityQueue<>((o1, o2) -> {
if (o1[0] == o2[0]) {
return o1[1] - o2[1];
}
else {
return o1[0] - o2[0];
}
});
Queue<int[]> rightMin = new PriorityQueue<>((o1, o2) -> {
if (o1[0] == o2[0]) {
return o1[1] - o2[1];
}
else {
return o1[0] - o2[0];
}
});
int curLen = n;
for (int i = 0; i < candidates; ++i) {
leftMin.offer(new int[]{costs[i], i});
rightMin.offer(new int[]{costs[n - 1 - i], n - 1 - i});
}
int leftIndex = candidates;
int rightIndex = n - candidates - 1;
while (curLen > 2 * candidates && k > 0) {
if (leftMin.peek()[0] <= rightMin.peek()[0]) {
res += leftMin.poll()[0];
leftMin.offer(new int[]{costs[leftIndex], leftIndex});
leftIndex += 1;
curLen -= 1;
}
else {
res += rightMin.poll()[0];
rightMin.offer(new int[]{costs[rightIndex], rightIndex});
rightIndex -= 1;
curLen -= 1;
}
k -= 1;
}
while (k > 0) {
if (leftMin.isEmpty()) {
res += rightMin.poll()[0];
}
else if (rightMin.isEmpty()) {
res += leftMin.poll()[0];
}
else {
res += (leftMin.peek()[0] <= rightMin.peek()[0] ? leftMin.poll()[0] : rightMin.poll()[0]);
}
k -= 1;
}
return res;
}
T4: 最小移动总距离
本题解答参考学习 灵茶山艾府 大佬的题解。
思路:动态规划
动态规划的使用前提条件
- 对于机器人
x和y,且位置x < y - 对于修理工厂
f1和f2,且位置f1 < f2 - 则移动距离最小的做法为
x-->f1, y-->f2
所以,将机器人和工厂均按位置排序后,有如下结论:
每个修理工厂维修的机器人是一个连续的序列
动态规划定义
dp[i][j]:前 i 个工厂修理前 j 个机器人的最小移动距离枚举第 i 个工厂修理的机器人个数 k
\[dp[i][j] = Math.min(dp[i-1][j-k] + cost, dp[i][j]) \qquad (0 \le k \le min(j, factory[i][1]))
\]
public long minimumTotalDistance(List<Integer> robot, int[][] factory) {
int[] robotArr = new int[robot.size()];
robotArr = robot.stream().mapToInt(i -> i).toArray();
Arrays.sort(robotArr);
Arrays.sort(factory, (o1, o2)->{
return o1[0] - o2[0];
});
int m = robotArr.length;
int n = factory.length;
long[][] dp = new long[n + 1][m + 1];
/**
* 初始化
* dp[i][0] = 0
* dp[i][1] = inf
*/
for (int i = 0; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = (long) 1e18;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
// k = 0 的情况
dp[i][j] = Math.min(dp[i][j], dp[i - 1][j]);
// 枚举第 i 个工厂修理了 k 个机器人
// 则前 i - 1 个工厂修理 j - k 个机器人
long cost = 0;
for (int k = 1; k <= Math.min(j, factory[i - 1][1]); k++) {
cost += Math.abs(factory[i - 1][0] - robotArr[j - k]);
dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - k] + cost);
}
}
}
return dp[n][m];
}
由于第i层的状态 dp[i] 的状态只和上一层 dp[i-1]的状态有关,所有该 dp 数组可以状态压缩
注意:状态压缩时,需要倒序遍历 robot ,保证状态覆盖的顺序是正确的
public long minimumTotalDistanceCompressDP(List<Integer> robot, int[][] factory) {
int[] robotArr = new int[robot.size()];
robotArr = robot.stream().mapToInt(i -> i).toArray();
Arrays.sort(robotArr);
Arrays.sort(factory, (o1, o2)->{
return o1[0] - o2[0];
});
// DP
int m = robotArr.length;
long[] dp = new long[m + 1];
for (int i = 1; i < dp.length; i++) {
dp[i] = (long) 1e18;
}
dp[0] = 0;
for (int[] fa : factory) {
for (int j = m; j >= 1; j--) {
long cost = 0;
for (int k = 1; k <= Math.min(j, fa[1]); k++) {
cost += Math.abs(fa[0] - robotArr[j - k]);
dp[j] = Math.min(dp[j], dp[j - k] + cost);
}
}
}
return dp[m];
}
LeeCode 318周赛复盘的更多相关文章
- leecode系列--Two Sum
学习这件事在任何时间都不能停下.准备坚持刷leecode来提高自己,也会把自己的解答过程记录下来,希望能进步. Two Sum Given an array of integers, return i ...
- 周赛-KIDx's Pagination 分类: 比赛 2015-08-02 08:23 7人阅读 评论(0) 收藏
KIDx's Pagination Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) S ...
- Win8制作和使用恢复盘
制作和使用恢复盘要制作恢复盘,请执行以下操作:注:确保计算机连接到交流电源.1. 将指针移至屏幕的右上角或右下角以显示超级按钮,然后单击搜索.2. 根据操作系统的不同,执行以下某项操作:• 在 Win ...
- OBIEE 11g:Error:nQSError 36010 Server version 318 cannot read the newer version of the repository
biee11g升级到最新版以后,发现了一些bug,需要回退到原来的版本,卸载掉升级包以后,启动BI服务,会报上述错误.这是因为资料库文件已经升级为了最新版本.这时候我们需要将资料库文件进行降版本操作. ...
- insertion Sort List (链表的插入排序) leecode java
逻辑简单,代码难写,基础不劳,leecode写注释不能出现中文,太麻烦,我写了大量注释,链表问题最重要的就是你那个指针式干啥的 提交地址https://oj.leetcode.com/problems ...
- 后续遍历 java leecode
以前觉得后续遍历最难写,今天看了篇博客http://blog.csdn.net/sgbfblog/article/details/7773103,其实却是我们仔细比较后续遍历和先序遍历,其实后续遍历就 ...
- 非递归实现先序遍历 java leecode 提交
写完才知道自己学习都是似是而非啊,大家可以也在leecode上提交代码,纯手写,离开eclipse第一种方式:数据结构书上的,使用栈大概思路.1.不断将根节点的左孩子的左孩子直到为空,在这个过程入栈. ...
- leecode 归并排序 链表(java)
写了好久,终于写成了.第一次zai leecode错题,题目质量很高,适合面试,与 1.归并排序是稳定的,在java中 Arrays.sort(a);中对于对象的排序就是归并排序.对于原子类型数据使用 ...
- bug修复复盘
mybatis与数据库交互时,报了莫名其妙的错,日志中显示的Stack Trace中报错的代码行数与IDE中还一致,逐重启tomcat,异常消失. 故障复盘:没有重启tomcat,使用copy命令直接 ...
- Swing开发界面时的一个bug复盘
问题:QA突然发个截图说一个Dialog上展示的东西变形了 分析:不理解,什么也没做,怎么会变形,刚刚我用的时候还正常.看看代码,的确什么也没更改:在本地测一下,也没有问题:baidu,bing,st ...
随机推荐
- Linux_Tomcat实战
Tomcat实战 tomcat简述 tomcat安装 部署jspgou项目 tomcat简述 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(A ...
- java从键盘输入数据
一.从键盘输入字符串 1.nex和nextLine的区别 next()读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键.Enter键或Tab键等结束符,next()会自动将其去掉,只有在 ...
- github使用流程
前期硬件准备工作(电脑相关配置): 1.下载git软件,傻瓜式安装 https://git-scm.com/download/win 2.设置你的用户名称与邮件地址 git config --glob ...
- 第12组 Beta冲刺 (1/5)
1.1基本情况 ·队名:美少女战士 ·组长博客: https://www.cnblogs.com/yaningscnblogs/p/14016591.html ·作业博客:https://edu.cn ...
- NuGet国内镜像
NuGet国内镜像 https://nuget.cdn.azure.cn/v3/index.json
- Linux应用开发之【多线程开发-回调函数】
原来我一直都不懂回调函数是什么 ... Callback Function 定义:通过函数指针调用的函数 在理解这个回调函数之前我们需要先了解回调机制 回调机制在编程中体现在:特定的情况发生后,返回并 ...
- 如何利用 C# + Echarts 绘制 Bar Simple
背景 Echarts 是百度推出的一个使用 JavaScript 实现的开源可视化库. 该库提供了常规的折线图.柱状图.散点图.饼图.K线图,用于统计的盒形图,用于地理数据可视化的地图.热力图.线图, ...
- Spring日志与SpringBoot日志
本篇意为说明Spring默认日志实现与SpringBoot默认日志实现. 1.日志 在这之前,我们应该先了解一些日志框架. 具体可以看我这篇随笔:https://www.cnblogs.com/dai ...
- C 系列的暂停
由于Mooc上有关C 的课程并不是很全面,网络上有关于C 的消息过于杂糅,所以暂时停止C的学习,重启时间暂定,等什么时候需要的时候再做重启.
- revit添加扩展组件
revit 添加组件方法: 查找本地这个地址: C:\Users\用户名\AppData\Roaming\Autodesk\Revit\Addins\2018 下载网上找到的插件,一般从github查 ...