我正在努力解决面试时提出的问题。我在面试时无法解决这个问题,所以我要求你帮忙知道。
问题是:
使用带整数的方法编写一个类,并返回在过去十分钟内调用该方法的最大值的整数。
根据我的理解,我必须存储过去10分钟调用该方法的所有值。值应存储在高效的数据结构中,因为此方法可能每秒调用几次。
对于哪种数据结构对此更有效,您有什么建议吗? 此外,由于这是一个时间滚动窗口,如何清除过期的值?
根据所使用的数据结构,获取最大值的最佳方法是什么?
我有一些基本代码:
private final static ScheduledExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadScheduledExecutor();
private static List<Integer> values = new ArrayList<Integer>();
public int method(final int value){
values.add(value);
// Task to remove the key-value pair
Runnable task = new Runnable() {
@Override
public void run() {
values.remove(value);
}
};
// Schedule the task to run after the delay
EXECUTOR_SERVICE.schedule(task, 60, TimeUnit.SECONDS);
//TODO get the max value
return 1;
}
答案 0 :(得分:5)
将Entry
类定义为(时间戳)time
和(int)value
;
使用LinkedList<Entry>
保持滑动窗口:在结尾插入,在开头删除过期。使用TreeMap<Integer, ArrayList<Entry>>
保持O(1)查找最大值(使用.lastEntry()
获取最大值)。我们的想法是按value
排序并保留具有该值的所有条目的列表;对于添加或删除的每个条目,必须更新树(在O(log(N))中一次。
不要使用调度程序;每当新请求到达时(或者请求“最大”)进行清理,它会更便宜,更快。
答案 1 :(得分:2)
这实际上可以在摊还的常数时间内完成:
values := deque of timestamped values
function prune()
while values.front is older than 10 minutes
values.pop_front()
function add(v)
while values is not empty and v is greater than values.back
values.pop_back()
values.push_back(v)
function getMax()
prune()
return values.front()
使用观察结果以递减的顺序存储值,当您获得新值时,您可能会忘记较小的旧值。
答案 2 :(得分:1)
关于您的代码的一些评论:
values.remove(value);
正在调用remove(int index)
而不是remove(Object o)
。因此它将删除位于index =值的值。您可以使用values.remove(Integer.valueOf(value));
代替备选方案1:
创建一个持有者类:
class Holder {
private static AtomicInteger staticVersionCounter = new AtomicInteger();
private int value;
private int version;
}
当您收到新的int
时,请创建new Holder(value, staticVersionCounter.incrementAndGet());
并将其放在TreeSet
中,并使用自定义比较器按升序值和版本进行排序(以确保相同值不会被覆盖)
TreeSet#last()
方法答案 3 :(得分:0)
我会使用LinkedList<IntegerTimePair>
这样做,你可以很容易地获得第一个元素,但也可以轻松地获取(和删除)元素(最旧的元素) - 一个LinkedList对此有好处,因为像ArrayList一样没有变化。我的第一个猜测是在某个时间间隔内检查,从列表的后面开始,删除所有超过十分钟的时间。
我唯一的问题是Java的LinkedList是否是双向的并且保持开头和结尾。如果没有,使用存储的尾指针写一个像removeFromEnd()这样的操作。
获取最大值可以使用列表扫描完成,或者通过保持最大值并仅在更高的值插入新值时更新,或者在删除时扫描最新的最大值(如果删除)最大值)。