解题报告-683. K Empty Slots
There is a garden with N slots. In each slot, there is a flower. The N flowers will bloom one by one in N days. In each day, there will be exactly one flower blooming and it will be in the status of blooming since then.
Given an array flowers consists of number from 1 to N. Each number in the array represents the place where the flower will open in that day.
For example, flowers[i] = x means that the unique flower that blooms at day i will be at position x, where i and x will be in the range from 1 to N.
Also given an integer k, you need to output in which day there exists two flowers in the status of blooming, and also the number of flowers between them is k and these flowers are not blooming.
If there isn't such day, output -1.
Example 1:
Input:
flowers: [1,3,2]
k: 1
Output: 2
Explanation: In the second day, the first and the third flower have become blooming.
Example 2:
Input:
flowers: [1,2,3]
k: 1
Output: -1
Note:
The given array will be in the range [1, 20000].
解法一: 时间O(N * LogN) 空间 O(N)
思路: 对于任意一个位置i, 假设i开花了, i 需要看下左侧离它最近的开花位置是不是i - k - 1, 或者看下右侧离它最近的位置是不是i + k + 1,
所以是个搜索问题. 搜索的话,我们知道有上下界查找,在java中,查数A的上界即找第一个大于该数的值,下界即找最后一个小于该数的值, 前提是整个数有序
而在本题中,我们可以使用treeset保存开花位置,每输入一个新的位置,在TreeSet中找左侧离该位置最近的位置,或者右侧离该位置最近的位置,即查找上下界
判断距离上下界的距离是否为k,第一个满足条件的为结果
class Solution {
public int kEmptySlots(int[] flowers, int k) {
TreeSet<Integer> tree = new TreeSet<>();
int day = 0;
for (int flower : flowers) {
++day;
tree.add(flower);
Integer lower = tree.lower(flower);
if (lower != null && flower - lower - 1 == k) return day;
Integer higher = tree.higher(flower);
if (higher != null && higher - flower - 1 == k) return day;
}
return -1;
}
}
解法二: 时间O(N) 空间O(N)
思路: 维护每个位置开花的日期, 如果存在某个区间符合条件,那么需要满足a[left] < min(a[left + 1] ... a[left + k]) && a[right] < min(a[left + 1] ... a[left + k])
可以考虑维护这个区间内的最小值,用两端的值跟区间内最小值比较,难点是该如何维护这个数据结构?
a[left] 要么比区间内的最小值大,要么等于,要么小于
因为我们要维护区间内的最小值,区间内的淘汰规则应该是小的淘汰大的,
所以如果a[left]比区间内的最小值小,那么假设我们维护了最小值队列,那么a[left]应该在区间前面
如果a[left]比区间内最小值大,那么它不会出现在最小值队列中
假设我们维护两个队列,一个存原始数据, 一个存区间内的最小值
假设left = 0, 第一个区间的right 应该为 k + 1
在入队第k个元素后,我们构造了前k个数的最小队列, a[left] 可能在队列中,也可能不在
我们先从原始队列中弹出a[left], 然后如果a[left] == 最小值队列的头部元素值,则从最小值队列中也把该值弹出
然后比较 a[left] 与 最小值队列当前的队头值,然后比较a[right]和最小值队头值, 如果满足条件a[left] < min(a[left + 1] ... a[left + k]) && a[right] < min(a[left + 1] ... a[left + k])
则得到一个可能的结果,最终从这些结果中,挑值最小的即为最终解
class Solution {
public int kEmptySlots(int[] flowers, int k) {
int[] days = new int[flowers.length];
for (int i = 0; i < days.length; i++) {
days[flowers[i] - 1] = i + 1;
}
int ans = Integer.MAX_VALUE;
MinQueue<Integer> mins = new MinQueue<>();
for (int i = 0; i < days.length; i++) {
mins.addLast(days[i]);
if (i >= k) {
Integer x = mins.pollFirst();
if (mins.isEmpty()) {
if (i + 1 < days.length) {
ans = Math.min(ans, Math.max(x, days[i + 1]));
}
} else {
if (x < mins.min() && i + 1 < days.length && days[i + 1] < mins.min()) {
ans = Math.min(ans, Math.max(x, days[i + 1]));
}
}
}
}
if (ans == Integer.MAX_VALUE) {
ans = -1;
}
return ans;
}
}
class MinQueue<E extends Comparable<E>> extends ArrayDeque<E> {
Deque<E> mins;
public MinQueue() {
mins = new ArrayDeque<E>();
}
@Override
public void addLast(E x) {
super.addLast(x);
while (mins.peekLast() != null && x.compareTo(mins.peekLast()) < 0) {
mins.pollLast();
}
mins.addLast(x);
}
@Override
public E pollFirst() {
E x = super.pollFirst();
if (0 == x.compareTo(mins.peekFirst())) {
mins.pollFirst();
}
return x;
}
public E min() {
return mins.peekFirst();
}
}
解法三: 时间O(N) 空间O(N)
思路: 与解法二思路相同, 维护K + 2大小的区间, 假设有两个满足条件的区间
[k1, k2] 和 [k3, k4], 可以得到一个结论: 这两个区间不能重合
因为假设两区间重合 k1 < k3 < k2 < k4, 那么k3 和 k4 中间存在一个比它俩都小的值,则[k3, k4]不满足解的条件,与已知条件矛盾
所以不可能重合.
同时对于一个区间内,如果遇到一个位置p, p < k1 或者 p < k2, 那么p之前位置都不可能是解, 此时,我们从p开始重新查找可行解.
class Solution {
public int kEmptySlots(int[] flowers, int k) {
int[] days = new int[flowers.length];
for (int i = 0; i < days.length; i++) {
days[flowers[i] - 1] = i + 1;
}
int left = 0, right = k + 1;
int ans = Integer.MAX_VALUE;
search:
while (right < days.length) {
for (int j = left + 1; j < right; j++) {
if (days[j] < days[left] || days[j] < days[right]) {
left = j;
right = j + k + 1;
continue search;
}
}
ans = Math.min(ans, Math.max(days[left], days[right]));
left = right;
right = left + k + 1;
}
if (ans == Integer.MAX_VALUE) ans = -1;
return ans;
}
}
解题报告-683. K Empty Slots的更多相关文章
- LC 683. K Empty Slots 【lock,hard】
There is a garden with N slots. In each slot, there is a flower. The N flowers will bloom one by one ...
- [LeetCode] 683. K Empty Slots K个空槽
There is a garden with N slots. In each slot, there is a flower. The N flowers will bloom one by one ...
- [LeetCode] K Empty Slots K个空槽
There is a garden with N slots. In each slot, there is a flower. The N flowers will bloom one by one ...
- 【九度OJ】题目1174:查找第K小数 解题报告
[九度OJ]题目1174:查找第K小数 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1174 题目描述: 查找一个数组的第 ...
- 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)
[LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...
- 【剑指Offer】链表中倒数第k个节点 解题报告(Python)
[剑指Offer]链表中倒数第k个节点 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://www.nowcoder.com/ta/coding-intervie ...
- 【LeetCode】402. Remove K Digits 解题报告(Python)
[LeetCode]402. Remove K Digits 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http: ...
- 【LeetCode】373. Find K Pairs with Smallest Sums 解题报告(Python)
[LeetCode]373. Find K Pairs with Smallest Sums 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/p ...
- 【LeetCode】692. Top K Frequent Words 解题报告(Python)
[LeetCode]692. Top K Frequent Words 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/top ...
随机推荐
- TF随笔-12
#!/usr/bin/env python2 # -*- coding: utf-8 -*- """ Created on Tue Aug 1 08:14:30 2017 ...
- python切片取值和下标取值时,超出范围怎么办?
可迭代对象下标取值超出索引范围,会报错:IndexError 可迭代切片取值超出索引范围,不报错,而是返回对应的空值. a=[1,2,3,4] a[99] Traceback (most recent ...
- Java第六次作业--异常处理和Java类集
Deadline: 2017-5-4 23:00 一.学习要点 认真看书并查阅相关资料,掌握以下内容: 理解Java的异常处理机制 掌握捕获异常和声明抛出异常的方法 掌握List接口的实现类Array ...
- OLEDB操作Excel
使用OLEDB操作Excel 的方法 OleDbConnection conn = null; try { //fileName ...
- Oracle XE自带数据库创建的过程
Oracle XE自带数据库如何创建的?XE.sql脚本定义实例究竟是怎样的?阅读下文,您可以找到这些问题的答案. Oracle XE自带数据库是如何创建的呢?这是很多人都提到过的问题,下面就为您详细 ...
- RK3288 开机动画旋转
CPU:RK3288 系统:Android 5.1 如果开机动画与屏显示方向不一致,有两种方法可以更改开机动画方向. 一.RK3288默认的开机动画是由两张图片组合而成的,可以直接旋转两张图片的方向. ...
- C# 转义字符 '\'反斜杠
在代码中经常用到表示路径的字符串,如何正确转换反斜杠? 如要将"C:\123"转换成"C:\\123" 如何转换? 方法: string str="C ...
- WebKit的已实施srcset图像响应属性
WebKit已经发布了一些官方新闻,终于落实srcset的属性.作为W3C的响应图像社区组的主席,我一直希望这一刻到来有一段时间了.所以,对所有参与方是个好消息,用户浏览网页时的体验是最重要的. 所有 ...
- week3-栈和队列
1.学习总结 2.PTA实验作业 2.1 题目1:7-1 jmu-报数游戏 2.2 设计思路(伪代码或流程图) 2.3 代码截图 2.4 PTA提交列表说明. 答案错误:error少了 !: 非零返回 ...
- 记一次 在 HP zbook G3 笔记本上安装Ubuntu16.04LTS 的 心(填)路(坑)旅程
背景 同事MM申请的新笔记本暂时没有用,问我需不需要用. 本着 “宇宙都是xx的”(厚颜无耻~~)思想就接受了. 拿到本本一看,HP zbook G3, 配置还不错(500G SSD, 16G mem ...