\quad 哈西表(hash table,也叫散列表),是根据关键字值(key)直接进行访问的数据结构,它通过把关键字映射到表中一个位置(数组下标)来直接访问,以加快查找关键字值的速度。这个映射函数叫做哈西(散列)函数,存放记录的数组叫做哈西(散列)表。
//哈西排序: 实践复杂度O(表长+n) n为元素个数
int random[10] = {999,1,44,555,666,8,12,902,11,520}; //在0-1000中的随意取值
int hash_map[1000] = {0};
for(int i=0; i<10; ++i)
++hash_map[random[i]];
for(int i=0; i<1000; ++i)
for(int j=0; j<hash_map[i]; ++j)
cout<< i <<'\t';
cout<<"排序完成";
Q1:
struct ListNode
{
int val;
ListNode* next;
ListNode(int x): val(x), next(NULL){}
};
//利用对表取余解决哈希映射
int hash_func(int key, int table_len)
{
return key%table_len;
}
//利用单链表解决哈西冲突
//插入value值
void insert(ListNode*hash_table[], ListNode* node, int table_len)
{
int hash_key = hash_func(node->val, table_len);
node->next = hash_table[hash_key];
hash_table[hash_key] = node; //使用头插法将value插到表对应位置的后接链表上
}
bool search(ListNode* hash_table[], int value, int table_len)
{
int hash_key = hash_func(value, table_len);
ListNode* head = hash_table[hash_key];
while(head)
{
if(head->val == value)
return true;
head = head->next;
}
return false;
}
int longestPalindrome(string s)
{
int Max_Len = 0;
int hash_map[128] = {0}; //建立字符哈西表
int flag = 0; //奇数字符标识
for(atuo K:s)
{
++hash[K]; //统计字频
}
for(int i=0; i<128;++i)
{
if(hash_map[i]%2==0)
Max_Len += hash_map[i];
else
{
Max_Len += (hash_map[i]-1); //奇数字符丢弃一个再入果
flag = 1;
}
}
return Max_Len + flag;
}
//一开始的时候想找最长奇数字符入果,其实是所有奇数字符均课入果,只不过要丢弃一个。
bool wordPattern(string pattern, string str)
{
map<string,char> hash_map;
int flag[26] = {0}; //标识hash_value是否已被使用
string word; //记录当前单词
int pos; //记录当前pattern的字符位置
str.push_back(' ');//为str最末尾单词添加‘ ’,作为单词切割标识符
for(int i=0; i<str.size();++i)
{
if(str[i]!=' ')
word+=str[i];
else
{
if(pos==pattern.size()) //有单词,没有pattern了,异常退出
return false;
else
{
if(hash_map.find(word)!=hash_map.end()) //当前单词再hash_map中没有key
{
if(flag[pattern[pos]-'a'])
return false; //如果当前字符已经被使用,说明哈西冲突的存在,异常退出
hash_map[word] = pattern[pos]; //建立单词到字符的映射关系
flag[pattern[pos]-'a']=1; //标识pattern已经被使用
}
else //当前单词已经在hash_map中
{
if(hash_map[word]!=pattern[pos]) //有hash冲突
return false;
}
word = "";
++pos;
}
}
}
if(pos!=pattern.size()) //还有pattern字符,异常退出
return false;
return true;
}
A:利用排序构建排序后的单词与原单词的哈希,异位词排序后会映射到同一个哈希表。
//利用排序后一样 构建哈希函数
vector<vector<string>> groupAnagrams(vector<string>& strs)
{
map<string,vector<string>> hash_map;
for(auto s:strs)
{
string temp = s;
sort(s.begin(),s.end()); //构建key
hash_map[s].push_back(temp);//构建value表
}
vector<vector<string>> result;
for(auto k:hash_map)
{
result.push_back(i.second);
}
return result;
}
A:设置双指针,并使用哈希表记录字符个数,一旦出现2即移动begin指针,将begin指针移到重复字符的下一个位置,
int lengthOfLongestSubstring(string s)
{
string word = "";
int result=0;
int begin = 0;
int char_map[128] = {0};
for(int i=0;i<s.size();++i)
{
++char_map[s[i]];
if(char_map[s[i]]==1)
{
word += s[i];
if(result<word.size())
result = word.size();
}
else
{
while(begin<=i && char_map[s[i]]>1)
{
--char_map[s[begin]];
++begin;
}
word = "";
for(int j=begin; j<=i; ++j)
word += s[j];
}
}
return result;
}
A: 利用位运算将DNA序列看出一个4进制数,通过哈西映射到2^20次方的下标中。
vector<string> findRepeatedDnaSequences(string s)
{
vector<int> hash_map(2^20,0); //建立哈西表
vector<string> res; //结果数组
int char_map[128] = {0};
int key = 0;
for(int i=9; i>=0; ++i)
key = key<<2 + char_map[s[i]];
hash_map[key] = 1;
for(int i=10; i<s.size();++i)
{
key = key>>2;
key = key | (char_map[s[i]]<<18);
++hash_map[key];
}
for(int i=0; i<(2<<20); ++i)
{
if(hash_map[i]>1)
res.push_back(change_int_to_DNA(i));
}
return res;
}
string chang_int_to_DNA(int i)
{
static char DNA = {'A','C','G','T'};
string str;
for(int i=0; i<10; ++i)
{
str += DNA{DNA&3};
DNA = DNA>>2;
}
return str;
}
//用无序哈希表来存储
vector<string> res;
vector<string> findRepeatedDnaSequences(string s)
{
if(s.size()<10) return res;
unordered_map<string,int> counter;
for(int i=0; i<s.size()-9;++i)
{
string t = s.substr(i,10);
if(counter[t]==1)
res.push_back(t);
++counter[t];
}
return res;
}
A:利用双指针,并记录当前子串长,和含T的字符个数,达到个数,更新子串,优化左指针,否则,优化右指针。
class Solution {
public:
string minWindow(string s, string t)
{
int hash[256] = {0};
for(auto c:t) ++hash[c];
int start = 0;
int end = 0;
int res = -1;
int cnt = 0;
string ans = "";
int m = t.size();
int n = s.size();
int length = -1;
while(end<n)
{
char c = s[end];
--hash[c];
if(hash[c]>=0) ++cnt;
while(cnt==m)
{
if(length==-1 || length>end-start+1)
{
length = end - start +1;
ans = s.substr(start,length);
}
c = s[start];
++hash[c];
if(hash[c]>=1) --cnt;
++start;
}
++end;
}
return ans;
}
};