l两周以来,第一次睡了个爽,开心!
=================================
leetcode380 https://leetcode.com/problems/insert-delete-getrandom-o1/?tab=Description
leetcode381 https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed/
leetcode532 https://leetcode.com/problems/k-diff-pairs-in-an-array/?tab=Description
====================================================================
380讲的是
设计一个数据结构,要求可以在O(1)的时间内完成以下操作
1,插入一个数字(如果不存在的话)
2,删除一个数字(如果存在的话)
3,随机返回一个数字(要求已存在的数字被返回的概率均等)
我的思路
一开始其实是一脸懵逼的,后来看了讨论版才明白。。
如果只有前两个要求,就是普通的hash表,连冲突处理都不需要,加上第三个要求后,要求把数据映射在0——n-1上,那就双向hash好了。。。
用a数组来存储数据,无序的
用unordered_map v来存贮数据在a中的下标,可以实现O(1)的数据定位。
插入简单,删除的时候永远删掉“a中最后的数据”,如果目标数据不是最后的,只需要把它换到最后就好,注意map中存的下标值也随之改变了
1 class RandomizedSet { 2 public: 3 vector<int> a; 4 unordered_map<int,int> v; 5 int n; 6 7 /** Initialize your data structure here. */ 8 RandomizedSet() { 9 a.clear(); 10 v.clear(); 11 srand(time(NULL)); 12 n=0; 13 } 14 15 /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */ 16 bool insert(int val) { 17 if(v.find(val)!=v.end())return false; 18 a.push_back(val); 19 v[val]=n++; 20 return true; 21 } 22 /** Removes a value from the set. Returns true if the set contained the specified element. */ 23 bool remove(int val) { 24 if(v.find(val)==v.end())return false; 25 unordered_map<int,int>::iterator it=v.find(val); 26 int ptr=it->second; 27 if(ptr!=n-1){ 28 v[a[n-1]]=ptr; 29 a[ptr]=a[n-1]; 30 } 31 v.erase(it); 32 a.resize(--n); 33 return true; 34 } 35 36 /** Get a random element from the set. */ 37 int getRandom() { 38 int ptr=rand()%n; 39 return a[ptr]; 40 } 41 }; 42 43 /** 44 * Your RandomizedSet object will be instantiated and called as such: 45 * RandomizedSet obj = new RandomizedSet(); 46 * bool param_1 = obj.insert(val); 47 * bool param_2 = obj.remove(val); 48 * int param_3 = obj.getRandom(); 49 */
====================================================================
381讲的是
设计一个允许重复数据的数据结构,要求可以在O(1)的时间内完成以下操作
1,插入一个数字(如果存在的话返回false)
2,删除一个数字(如果存在的话返回true)
3,随机返回一个数字(要求已存在的数字被返回的概率均等)
我的思路
一开始感觉直接直接把380的代码改成multimap就行,结果交了一发发现行不通,a中最后一个数据不知道对应在map中的哪儿(因为可能有多个)
多个数据的话我们在map中使用vector来存储就可以,为了O(1)定位,我们在a中使用pair来存储val和map第二维的下标
思考后发现a.back()代表的val一定是相同值最后一次出现的,所以我们只要交换m.find(val).back()和m[a.back().val][a.back().index]就行
1 class RandomizedCollection { 2 public: 3 /** Initialize your data structure here. */ 4 RandomizedCollection() { 5 6 } 7 8 /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */ 9 bool insert(int val) { 10 auto result = m.find(val) == m.end(); 11 12 m[val].push_back(nums.size()); 13 nums.push_back(pair<int, int>(val, m[val].size() - 1)); 14 15 return result; 16 } 17 18 /** Removes a value from the collection. Returns true if the collection contained the specified element. */ 19 bool remove(int val) { 20 auto result = m.find(val) != m.end(); 21 if(result) 22 { 23 auto last = nums.back(); 24 m[last.first][last.second] = m[val].back(); 25 nums[m[val].back()] = last; 26 m[val].pop_back(); 27 if(m[val].empty()) m.erase(val); 28 nums.pop_back(); 29 } 30 return result; 31 } 32 33 /** Get a random element from the collection. */ 34 int getRandom() { 35 return nums[rand() % nums.size()].first; 36 } 37 private: 38 vector<pair<int, int>> nums; 39 unordered_map<int, vector<int>> m; 40 };
1 class RandomizedCollection { 2 private: 3 vector<pair<int,int>> a; 4 unordered_map<int,vector<int> > m; 5 int n; 6 7 public: 8 /** Initialize your data structure here. */ 9 RandomizedCollection() { 10 a.clear(); 11 m.clear(); 12 srand(time(NULL)); 13 } 14 15 /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */ 16 bool insert(int val) { 17 bool result=(m.find(val)==m.end()); 18 m[val].push_back(a.size()); 19 a.push_back(pair<int,int>(val,m[val].size()-1)); 20 return result; 21 } 22 23 /** Removes a value from the collection. Returns true if the collection contained the specified element. */ 24 bool remove(int val) { 25 bool result=(m.find(val)!=m.end()); 26 if(result){ 27 pair<int,int> last=a.back(); 28 if(a.back().first!=val){ 29 m[last.first][last.second]=m[val].back(); 30 a[m[val].back()]=a.back(); 31 } 32 a.pop_back(); 33 m[val].pop_back(); 34 if(m[val].empty())m.erase(val); 35 } 36 return result; 37 } 38 39 /** Get a random element from the collection. */ 40 int getRandom() { 41 if(!a.size())return -1; 42 int ptr=rand()%a.size(); 43 return a[ptr].first; 44 } 45 }; 46 47 /** 48 * Your RandomizedCollection object will be instantiated and called as such: 49 * RandomizedCollection obj = new RandomizedCollection(); 50 * bool param_1 = obj.insert(val); 51 * bool param_2 = obj.remove(val); 52 * int param_3 = obj.getRandom(); 53 */
RE一万年,发现是忽略了“remove时如果m[val]已经被删空,应该erase掉”这种情况
还是挺有趣的一道题目。
====================================================================
532讲的是
输入n个数字a[i](无序,-1e7<=a[i]<=1e7,n<=1e4)和一个数字k,问你其中有多少不同的数对。
数对的定义:(i,j)是数对当且仅当abs(i-j)==k
我的思路
暴力的话就是排序去重,然后一个个压到hash中判断加减k是否有数据。O(nlogn)
后来想了想,感觉O{n}也可以,永远用后进入的数字来匹配之前的,就可以保证不重复。(如果有重复的数字要进入,就跳过)。
然后发现k居然可以等于0,丧心病狂,分开处理好了。。。
1 class Solution { 2 public: 3 int findPairs(vector<int>& nums, int k) { 4 int ans=0; 5 int n=nums.size(); 6 if(n<2)return 0; 7 unordered_map<int,int> m; 8 if(k){ 9 if(k<0)return 0; 10 for(int i=0;i<n;i++){ 11 int temp=nums[i],aim; 12 if(m.find(temp)!=m.end())continue; 13 aim=temp+k; 14 if(m.find(aim)!=m.end())ans++; 15 aim=temp-k; 16 if(m.find(aim)!=m.end())ans++; 17 m[temp]=1; 18 } 19 }else{ 20 for(int i=0;i<n;i++){ 21 int temp=nums[i]; 22 if(m.find(temp)!=m.end()){ 23 if(m[temp]==1){ 24 ans++; 25 m[temp]++; 26 } 27 }else{ 28 m[temp]=1; 29 } 30 } 31 } 32 return ans; 33 } 34 };
又是一道可以用python一行解决的题目(害怕)
1 def findPairs(self, nums, k): 2 return len(set(nums)&{n+k for n in nums}) if k>0 else sum(v>1 for v in collections.Counter(nums).values()) if k==0 else 0
展开是这样的
1 def findPairs(self, nums, k): 2 if k>0: 3 return len(set(nums)&set(n+k for n in nums)) 4 elif k==0: 5 return sum(v>1 for v in collections.Counter(nums).values()) 6 else: 7 return 0