剑指 Offer II 030. 插入、删除和随机访问都是 O(1) 的容器
思路分析
-
题目要求插入和删除(包括判断数据集是否包含一个数值)的时间复杂度都为o(1),能够同时满足这些时间效率的只有哈希表
-
如果只用哈希表则不能够等概率的返回数组中的每个数值。
-
如果数值是保存在数组当中,那么直接随机数对数组长度求余就OK
return nums[rand()%nums.size()]
-
-
数值保存在数组当中,因此我们需要直到每个值在数组当中的位置
- 否则就需要遍历整个数组才可以找到就变成o(n)了
-
将数值在数组中对应的位置保存在Hash表中
- 其中键为:数值
- 对应的值:数组当中的位置
具体的思路
-
在添加新的数值之前需要判断数据集当中是否已经包含该数值,如果数据集中已经包含该数值,直接返回false,如果没有该数值则直接添加到尾部就OK,并将其在数组中的下标添加到哈希表mp中
在mp和nums的尾部添加数据的操作的时间复杂度都是o(1)
-
在删除时同样先判断时否存在-如果不存在直接return false 如果包含该数值,则需要将其从mp中和nums中移除
-
在mp中移除直接调用
mp.erase(val)
-
从数组当中删除花费o(1)的时间复杂度时笔记麻烦一点的
-
需要先从mp中找到其对应的下标,但不能够直接删除,因为数组时连续的,如果直接删除则后面的数据则会移动填补,时间复杂度就成了o(n)
-
为了避免删除数组当中的数值要移动数据,则可以通过将要移除的数据和最后一个数据进行对应的交换,然后移除最后一个数据就OK
//先获取要移除元素的地址 int location=map[val]; //在mp中更新最后一个元素的地址为要移除元素的地址 mp[nums.back()]=location; //在mp中移除其对应的键 mp.erase(val); //将最后一个元素的值放到--被移除元素的位置 num[location]=nums.back(); //移除最后一个元素 nums.pop_back();
-
-
-
返回对应的随机值
代码
class RandomizedSet {
//定义一个hash表来保存其对应的值以及其地址
unordered_map<int,int>mp;
vector<int>nums;
public:
/** Initialize your data structure here. */
RandomizedSet() {
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val) {
//先判断其中时否存在
if(mp.count(val)){
return false;
}
nums.push_back(val);
//在这里要注意,因为数组的下标是从0开始,所以其对应的地址则为数组长度减去1
mp[val]=nums.size()-1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val) {
//不存在这个元素的值时返回false
if(!mp.count(val)){
return false;
}
//如果存在的话那么就要移除其元素
//第一步获取要移除元素的地址
int location=mp[val];
//将最有一个元素的地址变成要移除元素的地址
mp[nums.back()]=location;
//移除其对应的val
mp.erase(val);
//将数组中最后一个元素的值放到location的位置
nums[location]=nums.back();
//移除最后一个元素
nums.pop_back();
return true;
}
/** Get a random element from the set. */
int getRandom() {
//返回数组的随机值
return nums[rand()%nums.size()];
}
};
/**
* 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();
*/
剑指 Offer II 032. 有效的变位词
思路:
- 如果s的长度和t的长度不相等或者s==t的时候直接返回false
- 用数组来模拟一个哈希表
- 先遍历s字符串,记录每个字母出现的次数
- 遍历t字符串-如果当中不存在这个字符那么直接返回false,否则将个数减一
代码
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.length()!=t.length()||s==t){
return false;
}
//用数组来模拟哈希
//在这里一定要注意对数组进行初始化
int hash[26]{0};
for(auto ch:s){
//如果有这个字母则这个字母的值+1
hash[ch-'a']++;
}
for(auto ch:t){
//如果在数组当中不存在这个值,那么直接返回false
//否则的化对应的值--
if(hash[ch-'a']==0){
return false;
}
hash[ch-'a']--;
}
return true;
}
};