之前都是数组的操作,接下来介绍的数据结构是set,map, set 和map是C++中的容器;
首先复习一下set的基本使用,set数据结构内的数据是没有重复数据的,unique
#include<set> #include<iostream> using namespace std; int main() { int i; int arr[5] = {0,1,2,3,4}; set<int> iset(arr,arr+5); iset.insert(5); cout<<"size:"<<iset.size()<<endl; cout<<"3 count = "<<iset.count(3)<<endl; iset.erase(1); set<int>::iterator ite1 = iset.begin(); set<int>::iterator ite2 = iset.end(); for(;ite1!=ite2;ite1++) { cout<<*ite1; } cout<<endl; ite1 = iset.find(3); if(ite1!=iset.end()) cout<<"3 found"<<endl; ite1 = iset.find(1); if(ite1!=iset.end()) cout<<"1 not found"<<endl; }
基本操作是insert(),erase(),find(),change(map)改变map中的值的函数,由于C++中是使用二分搜索树来实现set和map所以插入,删除,查找的时间复杂度都是O(log(n))
关于集合的操作使用leetcode中的题型有:
leetcode 349:求解两个数组的交集
class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { //使用集合数据结构 set<int> unique(nums1.begin(),nums1.end()); set<int> ans; int i=0; int size=nums2.size(); for(i=0;i<size;i++){ if(unique.find(nums2[i])!=unique.end()){//uniques.find()返回的是迭代器类型 ans.insert(nums2[i]); } } vector<int> result(ans.begin(),ans.end()); return result; } };
时间复杂度为O(nlogn)
算法改进:使得时间复杂度为O(n),这时就需要用到两种数据结构 unordered_set和unordered_map,这两种数据结构的底层实现是通过hash表来实现的,所以插入和查找的时间复杂度为O(1)
class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { //使用集合数据结构 unordered_set<int> unique(nums1.begin(),nums1.end()); unordered_set<int> ans; int i=0; int size=nums2.size(); for(i=0;i<size;i++){ if(unique.find(nums2[i])!=unique.end()){ ans.insert(nums2[i]); } } vector<int> result(ans.begin(),ans.end()); return result; } };
以下是C++中map的基本使用,同样map的底层实现是通过二分搜索树实现的;
//插入元素: //用insert函數插入pair,成对的插入剪枝对的方式来构建 mapStudent.insert(pair<string, string>("r000", "student_zero")); //用"array"方式插入 mapStudent["r123"] = "student_first"; mapStudent["r456"] = "student_second";
C++中map有点类似于Python中defaultDict高级数据结构,默认值为0
leetcode 350 求两个数的交集,返回含有重复类型的数据
class Solution { public: vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { map<int,int> maps; vector<int> ans; int i=0; int size=nums1.size(); for(i;i<size;i++){ maps[nums1[i]]++;//默认值为0 } int size2=nums2.size(); for(int j=0;j<size2;j++){ if(maps.find(nums2[j])!=maps.end()){ maps[nums2[j]]--; if(maps[nums2[j]]>=0) ans.push_back(nums2[j]); } } return ans; } };
时间复杂度是O(nlog(n))
算法优化:使用unordered_map来进行构建数据
将map改为unordered_map<int,int>即可
leetcode242:判断一个字符串是否是自身变换的字符串
class Solution { public: bool isAnagram(string s, string t) { //使员工查找表数据结构来实现相应 hash map<char,int> maps; int i=0; int size=s.size(); for(i;i<size;i++){ maps[s[i]]++;//使用查找表统计出所有字符出现的频次 } int size2=t.size(); for(int j=0;j<size2;j++){ if(maps.find(t[j])!=maps.end()) maps[t[j]]--; else{ return false; } } //迭代器类型 容器类型 使用iter!=maps.end() map<char,int>::iterator iter=maps.begin(); for(iter;iter!=maps.end();iter++){ if(iter->second!=0){ return false; } } return true; } };
时间复杂度为O(nlogn)
同样将map改变unordered_map hash表的实现方式,时间复杂度为O(n)
leetcode202: 判断一个数是否是happy number,难点如何通过查找表来实现无限循环的退出
class Solution { public: bool isHappy(int n) { //使用一个map来存储每次计算的值,如果出现了重复那么就输出false map<int,int> maps; while(n!=1){ int sum=countSum(n); if(sum==1){ return true; } maps.insert(pair<int,int>(n,sum)); if(maps.count(sum)){//返回1或者0;; return false; } n=sum; } return true; } private: int countSum(int n){ int sum=0; while(n>0){ int temp=n%10; sum+=temp*temp; n=n/10; } return sum;} };
leetcode290: 判断两个字符串是否匹配;难点如何构建相互之间的映射
class Solution { public: bool wordPattern(string pattern, string str) { //首先符字符串进行分词,然后构建相互的映射 vector<string> mystring=split(str); map<char,string> mypatternMap; map<string,char> mystringMap; int i=0; int size=pattern.size(); if(pattern.size()!=mystring.size()){ return false; } for(i;i<size;i++){ if(mypatternMap.find(pattern[i])==mypatternMap.end()&&mystringMap.find(mystring[i])==mystringMap.end()){ mypatternMap.insert(pair<char,string>(pattern[i],mystring[i])); mystringMap.insert(pair<string,char>(mystring[i],pattern[i])); } else if(mypatternMap[pattern[i]]!=mystring[i]||mystringMap[mystring[i]]!=pattern[i]){ return false; } } return true; } private: vector<string> split(string str){ int i=0; int size=str.size(); vector<string> ans; int j=0; for(i;i<size;i++){ if(str[i]==' '){ ans.push_back(str.substr(j,i-j)); j=i+1; } if(i==size-1){ ans.push_back(str.substr(j,i-j+1));//包括当前元素 } } return ans; } };
时间复杂度为O(nlog(n)),插入元素的时间复杂度为O(log(n))
同理leetcode205 也是相应的方式,通过构建hashTable,查看两个字符串是否是结构匹配;
class Solution { public: bool isIsomorphic(string s, string t) { if(s.size()!=t.size()){ return false; } map<char,char> charMap1; map<char,char> charMap2; for(int i=0;i<s.size();i++){ if(charMap1.find(s[i])==charMap1.end()&&charMap2.find(t[i])==charMap2.end()){ charMap1.insert(pair<char,char>(s[i],t[i])); charMap2.insert(pair<char,char>(t[i],s[i])); } else if(charMap1[s[i]]!=t[i]||charMap2[t[i]]!=s[i]){ return false; } } return true; } };
时间复杂度为O(nlog(n))
接下来是leetcode451 Sort Characters By Frequency 按照字符出现的次数进行排序,返回排序后的字符串(核心就是如何对map中的值进行排序),使用数组,数组中的元素是pair类型的数据
class Solution { public: string frequencySort(string s) { //首先构建一个map来存储相应的hash结构,统计出现的频次 map<char,int> myMap; int i=0; int size=s.size(); for(i;i<size;i++){ myMap[s[i]]++; } //采用排序算法 // sort(myMap.begin(),myMap.end(),paixu); // string ans=""; // map<char,int>::iterator iter=myMap.begin(); // for(iter;iter!=myMap.end();iter++){ // int j=0; // while(j<iter->second){ // ans+=iter->first; // j++; // } // } // return ans; 以上算法不行 首先将pair元素push_back 到vector 中 vector<pair<char,int>> temp; map<char,int>::iterator iter=myMap.begin(); for(iter;iter!=myMap.end();iter++){ temp.push_back(pair<char,int>(iter->first,iter->second)); } sort(temp.begin(),temp.end(),paixu); int size2=temp.size(); string ans=""; for(int i=0;i<size2;i++){ int j=0; while(j<temp[i].second){ ans+=temp[i].first; j++; } } return ans; } private: static int paixu( const pair<char,int>& map1, const pair<char,int>& map2){// 需要static 否则不能通过; return map1.second>map2.second; } };
leetcode1 也可以用HashTable来实现,时间复杂大大降低
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { //使用hashtable int i=0; int size=nums.size(); map<int,int> myMap; vector<int> result; for(i;i<size;i++){ if(myMap.find(nums[i])!=myMap.end()){//如果有重复的元素出现 if(nums[i]==target-nums[i]){ result.push_back(myMap.find(nums[i])->second); result.push_back(i); return result; } } myMap[nums[i]]=i;// } map<int,int>::iterator iter=myMap.begin(); for(iter;iter!=myMap.end();iter++){ if(myMap.find(target-iter->first)!=myMap.end()){ map<int,int>::iterator iter2=myMap.find(target-iter->first); result.push_back(iter->second); result.push_back(iter2->second); return result; } } return result; } };
时间复杂度为O(nlogn),空间复杂度为O(n),运行时间13ms
如果将map换成unordered_map输出错误的结果?? 有谁知道为什么吗?