#include<iostream>
#include<vector>
#include<string>
using namespace std;
/**
哈希表和字符串
哈希表(hash table),是根据关键字值(key)直接进行访问的数据结构
它通过把关键字值映射到表中一个位置(数组下标)来直接访问
以加快查找关键字值的速度
(python中的字典数据结构就是基于哈希表实现的)
映射函数被称为哈希函数,存放记录的数组称为哈希表
给定表M,存在函数f(key),对任意的关键字值key,带入函数后若能得到包含
该关键字的表中地址,称表M为哈希表
**/
int main(){
int char_map[128]={0};
string a="abcdefgaaxxy";
// 统计字符串中各个字符的数量
for(int i=0;i<a.length();i++){
char_map[a[i]]++;
}
for(int i=0;i<128;i++){
char c;
cout<<"字符 "<<i<<"出现的次数:"<<char_map[i]<<endl;
}
return 0;
}
#include<iostream>
#include<stdio.h>
using namespace std;
/**
使用哈希表对数组进行排序:要求数组中的元素必须是非负的整数
使用数组的下标对正整数进行排序
哈希表的长度就等于待排序数组中可能的最大元素
**/
int main(){
int random[10]={999,1,444,7,20,9,1,3,7,7};
int hash_map_temp[1000]={0};
for(int i=0;i<10;i++){
hash_map_temp[random[i]]++;
}
for(int i=0;i<1000;i++){
for(int j=0;j<hash_map_temp[i];j++){
cout<<i<<endl;
}
}
return 0;
}
#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
/**
用拉链法解决冲突,构造哈希表
此时哈希表为指针数组,数组中的每个元素是一个指针
由指针引申出一条单链表
不同的元素value经过哈希函数映射后,可能得到相同的hash_key下标
此时为了避免冲突,并不是在哈希表的该索引位置处进行数值的累加
而是首先以value为数据域构建新的链表节点,
再以头插法的形式将新的链表节点插入到哈希表的对应位置处
**/
struct ListNode{
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL){}
};
int hash_func(int key,int table_len){
// 哈希函数,将key映射成在哈希表中的下标
return key%table_len;
}
void insert_head(ListNode *hash_table[],ListNode *node,int table_len){
int hash_key=hash_func(node->val,table_len);
node->next=hash_table[hash_key]->next;
hash_table[hash_key]->next=node;
}
bool search_temp(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;
}
else{
head=head->next;
}
}
return false;
}
int main(){
const int TABLE_LEN=11;
ListNode *hash_table[TABLE_LEN]={NULL};
for(int i=0;i<TABLE_LEN;i++){
hash_table[i]=new ListNode(0);
}
vector<ListNode *> has_node_vec;
int test[8]={1,1,4,9,20,30,150,500};
for(int i=0;i<8;i++){
has_node_vec.push_back(new ListNode(test[i]));
}
for(int i=0;i<8;i++){
insert_head(hash_table,has_node_vec[i],TABLE_LEN);
}
cout<<"Hash table: "<<endl;
for(int i=0;i<TABLE_LEN;i++){
cout<<"["<<i<<"]: ";
ListNode *temp_row=hash_table[i]->next;
while(temp_row!=NULL){
cout<<"->"<<temp_row->val;
temp_row=temp_row->next;
}
cout<<endl;
}
for(int i=0;i<10;i++){
int hash_key=hash_func(i,TABLE_LEN);
ListNode *temp_row=hash_table[hash_key]->next;
bool find_flag=false;
while(temp_row!=NULL){
if(temp_row->val==i){
cout<<i<<" in the hash table "<<endl;
find_flag=true;
break;
}
temp_row=temp_row->next;
}
if(find_flag==false){
cout<<i<<" not in the hash table "<<endl;
}
}
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
/**
leetcode 409 最长回文串
使用哈希表统计字符出现的次数
如果字符串出现的次数是偶数,则直接将出现次数累加到最终的次数上
如果字符串出现的次数是奇数,则将次数-1,累加到最终的次数上
**/
class Solution {
public:
int longestPalindrome(string s) {
// 统计字符串中各个字符出现的次数
int hash_map_temp[256]={0};
for(int i=0;i<s.length();i++){
hash_map_temp[s[i]]++;
}
bool find_odd=false;
int result=0;
for(int i=0;i<256;i++){
if(hash_map_temp[i]%2==0){
result+=hash_map_temp[i];
}
else{
find_odd=true;
result+=hash_map_temp[i]-1;
}
}
if(find_odd==true){
result+=1;
}
return result;
}
};
int main(){
string a="civilwartestingwhetherthatnaptionoranynartionsoconceivedandsodedicatedcanlongendureWeareqmetonagreatbattlefiemldoftzhatwarWehavecometodedicpateaportionofthatfieldasafinalrestingplaceforthosewhoheregavetheirlivesthatthatnationmightliveItisaltogetherfangandproperthatweshoulddothisButinalargersensewecannotdedicatewecannotconsecratewecannothallowthisgroundThebravelmenlivinganddeadwhostruggledherehaveconsecrateditfaraboveourpoorponwertoaddordetractTgheworldadswfilllittlenotlenorlongrememberwhatwesayherebutitcanneverforgetwhattheydidhereItisforusthelivingrathertobededicatedheretotheulnfinishedworkwhichtheywhofoughtherehavethusfarsonoblyadvancedItisratherforustobeherededicatedtothegreattdafskremainingbeforeusthatfromthesehonoreddeadwetakeincreaseddevotiontothatcauseforwhichtheygavethelastpfullmeasureofdevotionthatweherehighlyresolvethatthesedeadshallnothavediedinvainthatthisnationunsderGodshallhaveanewbirthoffreedomandthatgovernmentofthepeoplebythepeopleforthepeopleshallnotperishfromtheearth";
Solution s;
cout<<s.longestPalindrome(a)<<endl;
return 0;
}
#include<iostream>
using namespace std;
#include<vector>
#include<string>
/**
leetcode 290. 单词规律
给定一种规律 pattern 和一个字符串 str
判断 str 是否遵循相同的规律。
这里的 遵循 指完全匹配,
例如,pattern里的每个字母和字符串 str 中的每个非空单词之间
存在着双向连接的对应规律
算法:
动态地扫描输入的长字符串str,并以空格为关键字分隔符得到
每一个单词,并得到当前pattern所对应的的字符,
构建哈希函数,即字符串与pattern中字符的映射关系
**/
class Solution {
public:
bool wordPattern(string pattern, string str) {
string hash_dict[256]={""};
// 构建哈希表,数组的每个元素是字符串类型
int i=0;
int word_index=0;
string temp_word="";
while(i<str.length()){
if(str[i]==' '){
bool is_in=false;
int j=0;
for(;j<256;j++){
if(hash_dict[j]==temp_word){
is_in=true;
break;
}
}
if(is_in==false){
if(hash_dict[pattern[word_index]]!=""){
return false;
}
else{
hash_dict[pattern[word_index]]=temp_word;
}
}
else{
if(pattern[word_index]!=j){
return false;
}
}
temp_word="";
word_index++;
}
else{
temp_word+=str[i];
}
i++;
}
if(pattern.length()!=word_index+1){
return false;
}
bool is_in=false;
int j=0;
for(;j<256;j++){
if(hash_dict[j]==temp_word){
is_in=true;
break;
}
}
if(is_in==false){
if(hash_dict[pattern[word_index]]==""){
return true;
}
else{
return false;
}
}
else{
if(pattern[word_index]!=j){
return false;
}
else{
return true;
}
}
}
};
int main(){
Solution s;
bool output=s.wordPattern("abba","fish whoops whoops fish");
cout<<output<<endl;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
/**
leetcode 49. 字母异位词分组
给定一个字符串数组,将字母异位词组合在一起。
字母异位词指字母相同,但排列不同的字符串。
输入字符串数组中的每个元素——字符串对应一个哈希表
将原始的字符串数组转换成哈希表数组后
再遍历哈希表数组,将哈希表数组相同的字符串放到同一个vector中
C++中局部变量的作用域
C++中变量的作用域是使用花括号{} 区分的
花括号内部的变量的作用域在整个花括号中都有效
比如我之前的bug
在for循环中定义了整型数组 int a[26]
在for循环中之后又有语句将数组push到vector b中
则下一次循环过程中对于整型数组a的修改将直接修改vector b中的元素
为了避免这个问题,使用vector来替代整型数组,但还是超时了
**/
class Solution {
public:
bool is_equal(vector<int> a,vector<int> b){
for(int i=0;i<26;i++){
if(a[i]!=b[i]){
return false;
}
}
return true;
}
vector<vector<string> > groupAnagrams(vector<string>& strs) {
vector<vector<string> > result;
vector<vector<int> > hash_table_array;
vector<int> temp_hash_table;
for(int i=0;i<strs.size();i++){
temp_hash_table.clear();
for(int m=0;m<26;m++){
temp_hash_table.push_back(0);
}
for(int j=0;j<strs[i].length();j++){
temp_hash_table[int(strs[i][j])-97]++;
}
bool find_hash=false;
for(int k=0;k<hash_table_array.size();k++){
if(this->is_equal(hash_table_array[k],temp_hash_table)==true){
result[k].push_back(strs[i]);
find_hash=true;
break;
}
}
if(find_hash==false){
hash_table_array.push_back(temp_hash_table);
vector<string> temp_str;
temp_str.push_back(strs[i]);
result.push_back(temp_str);
}
}
return result;
}
};
int main(){
string a[6]={"eat", "tea", "tan", "ate", "nat", "bat"};
vector<string> strs;
for(int i=0;i<6;i++){
strs.push_back(a[i]);
}
Solution s;
vector<vector<string> > result=s.groupAnagrams(strs);
cout<<result.size()<<endl;
for(int j=0;j<result.size();j++){
cout<<"[ ";
for(int k=0;k<result[j].size();k++){
cout<<result[j][k]<<",";
}
cout<<" ]"<<endl;
}
return 0;
}
#include<iostream>
#include<vector>
#include<map>
using namespace std;
class Solution {
public:
bool is_equal(vector<int> a,vector<int> b){
for(int i=0;i<26;i++){
if(a[i]!=b[i]){
return false;
}
}
return true;
}
vector<vector<string> > groupAnagrams(vector<string>& strs) {
vector<vector<string> > result;
map<vector<int>,vector<string> > hash_table_array;
// 使用STL模板库实现的map映射函数
// 哈希表的key是当前字符串的对于各个字符的词频向量
// 哈希表的value是string
// STL 中的map对象具有find方法,查找当前的字典中是否包含某个键
vector<int> temp_hash_table;
for(int i=0;i<strs.size();i++){
temp_hash_table.clear();
for(int m=0;m<26;m++){
temp_hash_table.push_back(0);
}
for(int j=0;j<strs[i].length();j++){
temp_hash_table[int(strs[i][j])-97]++;
}
if(hash_table_array.find(temp_hash_table)==hash_table_array.end()){
// 当前的词频向量不存在于字典中
// C++中的map.find 函数是根据字典的关键字key进行查找的,如果字典不包含某个键
// 则返回map.end()
vector<string> temp_str;
temp_str.push_back(strs[i]);
hash_table_array.insert(make_pair(temp_hash_table,temp_str));
}
else{
hash_table_array[temp_hash_table].push_back(strs[i]);
}
}
// C++中对于map的遍历
map<vector<int>,vector<string> >::iterator iter;
for(iter=hash_table_array.begin();iter!=hash_table_array.end();iter++){
result.push_back((*iter).second);
}
return result;
}
};
int main(){
string a[6]={"eat", "tea", "tan", "ate", "nat", "bat"};
vector<string> strs;
for(int i=0;i<6;i++){
strs.push_back(a[i]);
}
Solution s;
vector<vector<string> > result=s.groupAnagrams(strs);
cout<<result.size()<<endl;
for(int j=0;j<result.size();j++){
cout<<"[ ";
for(int k=0;k<result[j].size();k++){
cout<<result[j][k]<<",";
}
cout<<" ]"<<endl;
}
return 0;
}
#include<iostream>
#include<vector>
#include<map>
using namespace std;
/**
leetcode 3. 无重复字符的最长子串
给定一个字符串,
请你找出其中不含有重复字符的 最长子串 的长度。
**/
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.length()<=1){
return s.length();
}
map<char,vector<int> > hash_dict;
int start_index=0;
int end_index=0;
int max_length=1;
while(end_index<s.length()){
// C++中map的find
/**
用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,
它返回数据所在位置的迭代器,
如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器
**/
map<char,vector<int> >::iterator iter;
iter=hash_dict.find(s[end_index]);
if(iter==hash_dict.end()){
// 如果在当前的字典中并没有找到字符
vector<int> temp;
temp.push_back(end_index);
hash_dict.insert(make_pair(s[end_index],temp));
}
else{
if(end_index-start_index>max_length){
max_length=end_index-start_index;
}
vector<int> temp_vector;
temp_vector=(*iter).second;
if(start_index<=temp_vector[temp_vector.size()-1]){
start_index=temp_vector[temp_vector.size()-1]+1;
}
(*iter).second.push_back(end_index);
}
end_index++;
}
if(end_index-start_index>max_length){
max_length=end_index-start_index;
}
return max_length;
}
};
int main(){
Solution s;
cout<<s.lengthOfLongestSubstring("abba")<<endl;
return 0;
}
#include<string>
#include<vector>
#include<map>
#include<iostream>
using namespace std;
/**
leetcode 187
所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,
例如:“ACGAATTCCG”。
在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。
编写一个函数来查找 DNA 分子中所有出现超多一次的10个字母长的序列(子串)。
**/
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
map<string,int> word_map;
vector<string> result;
for(int i=0;i<s.length();i++){
string temp_word=s.substr(i,10);
// 表示从字符串的索引下标i开始并向后连续取出10个字符
if(word_map.find(temp_word)!=word_map.end()){
word_map[temp_word]++;
}
else{
word_map.insert(make_pair(temp_word,1));
}
}
map<string,int> ::iterator iter;
for(iter=word_map.begin();iter!=word_map.end();iter++){
if((*iter).second>1){
result.push_back((*iter).first);
}
}
return result;
}
};
int main(){
Solution s;
vector<string> result;
result=s.findRepeatedDnaSequences("AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT");
for(int i=0;i<result.size();i++){
cout<<result[i]<<endl;
}
return 0;
}