C++

数据结构与算法

哈希表、字符串

Posted by Bob on September 15, 2019

以下题目均来自leetcode、poj

最长回文串

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。

在构造过程中,请注意区分大小写。比如 ”Aa” 不能当做一个回文字符串。

注意: 假设字符串的长度不会超过 1010。

示例 1:

输入: “abccccdd”

输出: 7

解释: 我们可以构造的最长的回文串是”dccaccd”, 它的长度是 7。


class Solution {
public:
    int longestPalindrome(string s) {
        int charMap[128] = 0;
        int maxLength = 0;
        int flag = 0;
        for (int i = 0; i < s.length(); i++) {
            charMap[s[i]]++;
        }
        for (int i = 0; i < 128; i++) {
            if(charMap[i] %2 ==  0){
                //字符为偶数全部可用

                max_length += charMap[i];
            }else{
                //为奇数 拿一个出来,最后当中心点

                max_length += charMap[i] - 1;
                flag = 1;
            }
        }
        reutrn max_length + flag;
    }
};

单词规律

给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。

这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。

示例1:

输入: pattern = “abba”, str = “dog cat cat dog” 输出: true 示例 2:

输入:pattern = “abba”, str = “dog cat cat fish” 输出: false 示例 3:

输入: pattern = “aaaa”, str = “dog cat cat dog” 输出: false 示例 4:

输入: pattern = “abba”, str = “dog dog dog dog” 输出: false 说明: 你可以假设 pattern 只包含小写字母, str 包含了由单个空格分隔的小写字母。 


class Solution {
public:
    bool wordPattern(string pattern, string str) {
        std::vector<std::string,char> word_map;
        char used[128] = {0};
        std::string word;
        int pos = 0;
        str.push_back(' ');
        for (i = 0; i < str.length();i++){
            if(str[i] == ' '){
                //找到最后都找不到

                if(pos == pattern.length()){
                    reutrn false;
                }
                if(word_map.find(word) == word_map.end()){
                    if(used[pattern[pos]]){
                        return false;
                    }
                    word_map[word] = pattern[pos];
                    used[pattern[pos]] = 1;
                }else{
                    if(word_map[word] != pattern[pos]){
                        return false;
                    }
                }
                word = "";
                pos++;
            }else{
                word += str[i];
            }
        }
        if(pos != pattern.length()){
            return false;
        }
        return true;
    }
};


字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”], 输出: [ [“ate”,”eat”,”tea”], [“nat”,”tan”], [“bat”] ] 说明:

所有输入均为小写字母。 不考虑答案输出的顺序。


class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        std::map<std::string,std::vector<std::string>> anagram;
        std::vector<std::vector<std::string>> result;
        for(int i = 0;i < strs.size();i++){
            std::string str = strs[i];
            std::sort(str.begin(),str.end());
            if(anagram.find(str) == anagram.end()){
                std::vector<std::string> item;
                anagram[str] = item;
            }
            anagram[str].push_back(strs[i]);
        }
        std::map<std::string,std::vector<std::string>> ::iterator it;
        for(it = anagram.begin();it != anagram.end();it++){
            result.push_back((*it).second);
        }
        return result;
    }
};



无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示例 2:

输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。 示例 3:

输入: “pwwkew” 输出: 3 解释: 因为无重复字符的最长子串是 ”wke”,所以其长度为 3。   请注意,你的答案必须是 子串 的长度,”pwke” 是一个子序列,不是子串。


class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int begin = 0;
        int result = 0;
        std::string word = "";
        int char_map[128] = {0};
        for(int i = 0;i < s.length();i++){
            char_map[s[i]]++;
            if(char_map[s[i]] == 1){
                word += s[i];
                if(result < word.length()){
                    result = word.length();
                }
            }else{
                //滑动到重复字符的下一个字符,
                while(begin < i && char_map[s[i]] > 1){
                    char_map[s[i]]--;
                    begin++;
                }
                word = "";
                for(int j = begin;j <= i;j++){
                    word+=s[j];
                }
            }   
        }
        return result;
    }
};



重复的DNA序列

所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。

编写一个函数来查找 DNA 分子中所有出现超多一次的10个字母长的序列(子串)。

示例:

输入: s = “AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT”

输出: [“AAAAACCCCC”, “CCCCCAAAAA”]


class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        vector<string> res;
        unordered_map<string, int> m;
        for (int i = 0; i <= int(s.size() - 10); ++i) {
            string str = s.substr(i,10);
            if (++m[str] == 2) {
                res.push_back(str);
            }
        }
        return res;
    }
};


最小覆盖子串

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。

示例:

输入: S = “ADOBECODEBANC”, T = “ABC” 输出: “BANC” 说明:

如果 S 中不存这样的子串,则返回空字符串 ““。 如果 S 中存在这样的子串,我们保证它是唯一的答案。


class Solution {
private:
    bool isWindowOk(int maps[],int mapt[],vector<int> &vect){
        for(int i= 0;i<vect.size();i++){
            if(maps[vect[i]] < mapt[vect[i]]){
                return false;
            }
        }
        return true;
    }
public:
    string minWindow(string s, string t) {
        const int MAPSIZE = 128;//char 0-127
        int mapt[MAPSIZE] = {0};
        int maps[MAPSIZE] = {0};
        std::vector<int> vect;
        for (int i = 0; i < t.length();i++){
            mapt[t[i]]++;
        }
        for (int i = 0; i < MAPSIZE;i++){
            if (m[i] > 0){
                vect.push_back(i);
            }
        }
        int  windowBegin = 0;
        std::string result;
        for (int i = 0; i < s.size();i++){
            maps[s[i]]++;
            while (windowBegin < i){
                char begin_ch = s[windowBegin];
                if(mapt[begin_ch] == 0){
                    //窗口头指针字符,不在t中
                    
                    windowBegin++;
                }
                else if (maps[begin_ch] > mapt[begin_ch]){
                    //窗口内有多的字符,移动窗口,减少计数

                    maps[begin_ch]--;
                    windowBegin++;
                }else{
                    break;
                }
            }
            if(isWindowOk(maps,mapt,vect)){
                int newWindowLen = i - windowBegin + 1;
                //更短的才更新

                if(result == "" || result.length() < newWindowLen){
                    result = s.substr(windowBegin,newWindowLen);
                }
            }
        }
        return result;
    }
};