LeetCode 面试经典150题---004

#### 274. H 指数

给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。
n == citations.length
1 <= n <= 5000
0 <= citations[i] <= 1000
本题题意就是给你一个数组,找到最大的h,使得数组中至少有h个数都大于等于h。考虑到本题的n较小,因此如果使用排序的话复杂度也只是\(nlogn\),不会超时。因此先把数组从小到大排序,可以看出h最大就是数组的长度,因此我们可以从最大值开始判断,i从0开始,如果此时nums[i]>=h,说明至少有h个数都大于等于h,直接输出答案,因为我们是从大到小枚举h。

class Solution {
public:
    int hIndex(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int n = nums.size();
        int h = n;
        for(int i = 0;i < n;i ++ ){
            if(nums[i] >= h) return h;
            else h --;
        }
        return h;
    }
};

本题还可以采用二分,因此h的值只会在1-n,因此我们在1-n之间二分,令mid=l + r + 1 >> 2,如果此时mid满足由mid个数都大于等于mid,我们令左区间l=mid;否则令右区间r=mid - 1。

class Solution {
public:
    int hIndex(vector<int>& nums) {
        int n = nums.size();
        int l = 0, r = n;
        while(l < r){
            int mid = l + r + 1 >> 1;
            if(check(nums, mid)) l = mid;
            else r = mid - 1;
        }
        return l;
    }

    bool check(vector<int> nums, int h){
        int cnt = 0;
        for(int i = 0;i < nums.size();i ++ ){
            if(nums[i] >= h) cnt ++;
        }
        if(cnt >= h) return true;
        return false;
    }

};

#### 380. O(1) 时间插入、删除和获取随机元素

实现RandomizedSet 类:
RandomizedSet() 初始化 RandomizedSet 对象
bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。
bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false 。
int getRandom() 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。
你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1) 。
\(-2^{31} <= val <= 2^{31} - 1\)
最多调用 insert、remove 和 getRandom 函数 2 * 105 次
在调用 getRandom 方法时,数据结构中 至少存在一个 元素。

本题就是模拟,直接根据题意一步步操作即可。首先对于插入,定义哈希表用来存储每个插入元素的下标和判断该元素是否存在,再定义一个数组用来存储元素,方便后面输出随机一个元素;对于删除,和插入类似,不过需要删除数组和哈希表的对应元素;对于随机一个元素,直接rand即可。

class RandomizedSet {
public:
    unordered_map<int, int> hash;
    vector<int> arr;
    int cnt = 0;

    RandomizedSet() {

    }
    
    bool insert(int val) {
        auto it = hash.find(val);
        if(it == hash.end()){
            hash[val] = cnt ++;
            arr.push_back(val);
            return true;
        }
        return false;
    }
    
    bool remove(int val) {
        auto it = hash.find(val);
        if(it != hash.end()){
            int item = it->second;
            arr[item] = arr.back();
            hash[arr[item]] = item;
            arr.pop_back();
            cnt --;
            hash.erase(val);
            return true;
        }
        return false;
    }
    
    int getRandom() {
        return arr[rand() % cnt];
    }
};

/**
 * Your RandomizedSet object will be instantiated and called as such:
 * RandomizedSet* obj = new RandomizedSet();
 * bool param_1 = obj->insert(val);
 * bool param_2 = obj->remove(val);
 * int param_3 = obj->getRandom();
 */

总结,整体比较简单,就是需要一点小技巧。

posted @ 2024-04-10 13:13  吃瓜吃撑了  阅读(20)  评论(0)    收藏  举报