[Leetcode] 379. Design Phone Directory 解题报告

题目

Design a Phone Directory which supports the following operations:

  1. get: Provide a number which is not assigned to anyone.
  2. check: Check if a number is available or not.
  3. 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);

思路

这道题目本身思路并不难,但是我们可以选择不同的数据结构进行实现和比较,进而加深对不同数据结构的理解。本文中我试了三种不同的数据结构,先从理论上分析一下它们的时间和空间复杂度,然后给出我测试的运行时间(这个可能不会太准确)。为了渐变,我们设n = maxNumbers,表示最多可以提供的电话号码个数。

1、哈希表:只需要存贮一个哈希表,所以空间复杂度理论上是O(n)(实际上存储空间应该比这个大,因为涉及到散列和解决冲突)。

PhoneDirectory(int maxNumbers):时间复杂度是O(n)。

int get():时间复杂度是O(1)。

bool check(int number):时间复杂度是O(1)。

void release(int number):时间复杂度是O(1)。

2、二叉搜索树:只需要存贮一棵二叉搜索树,所以空间复杂度是O(n)。

PhoneDirectory(int maxNumbers):时间复杂度是O(nlogn)。

int get():时间复杂度是O(logn)。

bool check(int number):时间复杂度是O(logn)。

void release(int number):时间复杂度是O(logn)。

3、数组:存储一个表示电话号码的数组,以及一个表示某个电话号码是否可用的数组,以及一个当前可用的电话号码个数。所以空间复杂度是O(2n)。

PhoneDirectory(int maxNumbers):时间复杂度是O(n)。

int get():时间复杂度是O(1)。

bool check(int number):时间复杂度是O(1)。

void release(int number):时间复杂度是O(1)。

通过对比可以发现,1和3的时间复杂度都较低,但是由于3中每个函数中同时要对两个数组进行操作,所以运行时间还是要略慢于1。这是不是也说明C++系统中实现的散列函数还是不错的,解决冲突并没有花费太多的时间?

代码

1、哈希表(1315ms):

class PhoneDirectory {
public:
    /** Initialize your data structure here
        @param maxNumbers - The maximum numbers that can be stored in the phone directory. */
    PhoneDirectory(int maxNumbers) {
        for (int i = 0; i < maxNumbers; ++i) {
            hash.insert(i);
        }
    }
    
    /** Provide a number which is not assigned to anyone.
        @return - Return an available number. Return -1 if none is available. */
    int get() {
        if (hash.empty()) {
            return -1;
        }
        int ret = *(hash.begin());
        hash.erase(hash.begin());
        return ret;
    }
    
    /** Check if a number is available or not. */
    bool check(int number) {
        return hash.count(number) > 0;
    }
    
    /** Recycle or release a number. */
    void release(int number) {
        hash.insert(number);
    }
private:
    unordered_set<int> hash;
};

/**
 * Your PhoneDirectory object will be instantiated and called as such:
 * PhoneDirectory obj = new PhoneDirectory(maxNumbers);
 * int param_1 = obj.get();
 * bool param_2 = obj.check(number);
 * obj.release(number);
 */

2、二叉搜索树(1445ms):

class PhoneDirectory {
public:
    /** Initialize your data structure here
        @param maxNumbers - The maximum numbers that can be stored in the phone directory. */
    PhoneDirectory(int maxNumbers) {
        for (int i = 0; i < maxNumbers; ++i) {
            st.insert(i);
        }
    }
    
    /** Provide a number which is not assigned to anyone.
        @return - Return an available number. Return -1 if none is available. */
    int get() {
        if (st.empty()) {
            return -1;
        }
        int ret = *st.begin();
        st.erase(st.begin());
        return ret;
    }
    
    /** Check if a number is available or not. */
    bool check(int number) {
        return st.find(number) != st.end();
    }
    
    /** Recycle or release a number. */
    void release(int number) {
        st.insert(number);
    }
private:
    set<int> st;
};

/**
 * Your PhoneDirectory object will be instantiated and called as such:
 * PhoneDirectory obj = new PhoneDirectory(maxNumbers);
 * int param_1 = obj.get();
 * bool param_2 = obj.check(number);
 * obj.release(number);
 */

3、数组(1362ms):

class PhoneDirectory {
public:
    /** Initialize your data structure here
        @param maxNumbers - The maximum numbers that can be stored in the phone directory. */
    PhoneDirectory(int maxNumbers) {
        n = maxNumbers;
        numbers.resize(n);
        for(int i = 0; i < n; ++i) {
            numbers[i] = i;
        }
        is_available.resize(n, true);
    }
    
    /** Provide a number which is not assigned to anyone.
        @return - Return an available number. Return -1 if none is available. */
    int get() {
        if(n == 0) {
            return -1;
        }
        int num = numbers[--n];
        is_available[num] = false;
        return num;
    }
    
    /** Check if a number is available or not. */
    bool check(int number) {
        return is_available[number];
    }
    
    /** Recycle or release a number. */
    void release(int number) {
        if(is_available[number]) {  // already released
            return;
        }
        numbers[n++] = number;
        is_available[number] = true;
    }
private:
    vector<int> numbers;            // the number array
    vector<bool> is_available;      // indicate whether the number is available
    int n;                          // the current available numbers
};

/**
 * Your PhoneDirectory object will be instantiated and called as such:
 * PhoneDirectory obj = new PhoneDirectory(maxNumbers);
 * int param_1 = obj.get();
 * bool param_2 = obj.check(number);
 * obj.release(number);
 */

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值