leetcode part7 哈希表与字符串

#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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值