- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我遇到了下面的面试问题,我能够想出以下解决方案:
Design a Phone Directory which supports the following operations:
get: Provide a number which is not assigned to anyone. check: Check if a number is available or not. release: Recycle or release a number..
Example: // Init a phone directory containing a total of 3 numbers: 0, 1, and 2.
PhoneDirectory directory = new PhoneDirectory(3);
// It can return any available phone number. Here we assume it returns 0.
directory.get();
// Assume it returns 1.
directory.get();
// The number 2 is available, so return true.
directory.check(2);
// It returns 2, the only number that is left.
directory.get();
// The number 2 is no longer available, so return false.
directory.check(2);
// Release number 2 back to the pool.
directory.release(2);
// Number 2 is available again, return true.
directory.check(2);
如果我们谈论的是 10 位真实电话号码并且初始化大约需要 o(n) 时间,面试官问这个解决方案的可扩展性如何。此外,如果我们非常频繁地删除,那么保留每个未使用的数字可能会浪费空间。他提到如果它也被用于多线程情况会发生什么。
这里有什么我们可以优化的吗?
public class PhoneDirectory {
private final Set<Integer> used = new HashSet<Integer>();
private final Queue<Integer> available = new LinkedList<Integer>();
private final int max;
public PhoneDirectory(int maxNumbers) {
this.max = maxNumbers;
for (int i = 0; i < maxNumbers; i++) {
this.available.offer(i);
}
}
public int get() {
Integer ret = available.poll();
if (ret == null) {
return -1;
}
used.add(ret);
return ret;
}
public boolean check(int number) {
if (number >= max || number < 0) {
return false;
}
return !used.contains(number);
}
public void release(int number) {
if (used.remove(number)) {
available.offer(number);
}
}
}
最佳答案
正如您的面试官所说,存储所有未使用的电话号码并不实际。我想从候选人那里看到一个很好的澄清问题是 get()
的频率是多少?和 release()
电话。对于现实世界的使用,它们可能以大致相同的频率发生,因此以下方法将起作用:
我们可以通过观察是否使用了任何不可用的内容来优化您的解决方案,因此实际上没有必要存储这两种状态。因此,让我们只跟踪未使用的那些。
public class PhoneDirectory {
private final Set<Integer> available = new HashSet<Integer>();
public PhoneDirectory(int maxNumbers) {
for (int i = 0; i < maxNumbers; i++) {
this.available.add(i);
}
}
public int get() {
if (available.isEmpty()) {
return -1;
}
int result = available.iterator().next();
available.remove(result);
return result;
}
public boolean check(int number) {
return available.contains(number);
}
public void release(int number) {
available.add(number);
}
}
这给了我们一个摊销 O(1)
除施工外的所有调用的操作。为了处理优化构造函数调用,我们可以做什么 Jason Armstrong提到并观察到我们可以跟踪迄今为止提供的最大数量,这意味着高于此数量的任何东西都可以提供。此外,如果它们存在,我们可以首先耗尽可用条目的稀疏集。看起来像这样
public class PhoneDirectory {
private final Set<Integer> available = new HashSet<Integer>();
private final int maxNumbers;
private int largestOffered;
public PhoneDirectory(int maxNumbers) {
this.maxNumbers = maxNumbers;
this.largestOffered = 0;
}
public int get() {
if (available.isEmpty()) {
return largestOffered < maxNumbers ? (++largestOffered) : -1;
}
int result = available.iterator().next();
available.remove(result);
return result;
}
public boolean check(int number) {
return available.contains(number) || number > largestOffered;
}
public void release(int number) {
available.add(number);
}
}
这摆脱了我们的 O(n)
构造函数。回到最初关于频率的假设,之所以可行,是因为如果 get()
和 release()
以相同的频率相对不可预测地发生,那么 available
的大小会保持相对稳定。这使数据结构的大小总体上保持相当高效。
如果调用的频率不同,例如我们预计 release()
一次可以释放大块,那么这个问题就变得复杂了很多。我相信一般来说,这个问题可以归结为位图操作,而节省空间的做法本质上是位级压缩。
关于您的面试官提出的后续问题,他们可能希望对分布式哈希表进行一些讨论。您还可以优化 available.iterator().next()
然后available.remove()
可以通过对底层数据结构的一些访问来简化调用。
关于java - 设计电话目录,为您提供从池中返回的号码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53619441/
我正在为我的程序编写安装脚本,它应该在 Linux/Unix 操作系统上运行。以下文件的默认目录是什么: 可执行文件(程序)。程序应通过从命令行键入其名称来执行。 共享库。 第三方共享库(程序未开源,
我有一堆用户、组和应用程序注册,我的 MVC 应用程序使用 AAD 数据进行身份验证和授权。是否可以将 Azure Active Directory 从一个租户(目录)迁移到另一个租户(目录)?如果可
查看 cljsbuild 文档 https://github.com/emezeske/lein-cljsbuild :cljsbuild { :builds [{ ; The
忽略已经版本控制的文件 如果你不小心添加了一些应该被忽略的文件,你如何将它们从版本控制中去除而不会丢失它们?或许你有自己的IDE配置文件,不是项目的一部分,但将会花费很多时间使之按照自己的方式工作。
我想使用\tableofcontents 命令,但没有目录从新页面开始或在末尾创建新页面,并且所有内容都是单倍行距。我怎样才能做到这一点?我假设使用 tocloft,但有哪些选择? 谢谢 最佳答案 试
我有一些 javascript 菜单代码,可以在单独的目录中正常工作。但是,当我尝试从同一目录中调用相同的 .js 文件时,它不会看到这些文件。 以下内容来自另一个目录: script type="t
我有这样的路径: /my/path/to/important_folder 在同一级别上,我还有其他文件和文件夹想要在达到与 important_folder 相同的级别时列出。 我的文件夹可能更深,
1、获取文件路径实现 1.1 获取当前文件路径 ? 1
我正在使用最新版本的 NTEmacs。 我写了一个名为“.dir-locals.el”的文件,如下所示。 ((nil . ((tab-width . 8) (fill-column .
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
在我的 .vimrc 中有这些行 :set foldmethod=marker :set foldmarker=SECTION:,ENDSECTION: 用于自定义代码折叠。在我的文件中,相关语言的注
在 fish 中: for x in * echo $x end *这里包括所有目录和文件,如何只列出文件(或目录)? 最佳答案 fish 没有很多花哨的通配语法。但是,目录可以像这样迭代: f
这是我的目录结构: ├── src │ ├── helpers │ │ ├── __init__.py │ │ ├── foo.py │ │ └── bar.py │
我想递归重命名文件夹/目录名称并找到 this solution所以。但是这个命令没有效果 find . -type f -exec rename 's/old/new/' '{}' \; 这是一个正
我想在相册中创建一个文件夹,并希望将图像保存在创建的相册中。 这可能吗?有什么办法可以做到这一点吗? 我已经搜索过,大多数人都说这是不可能的。 感谢您的帮助。 最佳答案 您也许可以使用AssetsLi
如何在python中使用用户定义的名称创建临时文件/目录。我知道 tempfile .但是我看不到任何以文件名作为参数的函数。 注意:我需要这个来对包含临时文件的临时目录上的 glob(文件名模式匹配
我在项目中使用JaCoCo Gradle插件。 作为问题的一个示例,我的大部分代码都在com.me.mysoftware包下。 我正在使用代码生成器来生成build/generated/java/..
我正在尝试使用 Gradle 开始运行 jar 文件 我的任务如下所示: task startServer(type: Exec) { workingDir file("${buildDir}/a
如何在 Ant 中定义一个目录集,其中包括两个目录:项目的基目录和子目录“test”? 看起来您无法使用“/”、“.”或“”专门包含目录集的根目录。例如,这包括“./test”,但不包括“.”:
我正在使用 CTAGs 包,它使用 Sublime Text 2 生成两个文件 .tags 和 .tags_sorted_by_file。 那么当我进行项目搜索(CMD + SHIFT + F)时,如
我是一名优秀的程序员,十分优秀!