目录
哈希表定义
字符哈希
哈希表排序整数
拉链法(解决一个key后面跟多个值的问题)
理论描述
代码实现
哈希表(拉链法).cpp
#include <stdio.h>
#include <vector>
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;
}
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;
}
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 main(){
const int TABLE_LEN = 11;
ListNode *hash_table[TABLE_LEN] = {0};
std::vector<ListNode *> hash_node_vec;
int test[8] = {1, 1, 4, 9, 20, 30, 150, 500};
for (int i = 0; i < 8; i++){
hash_node_vec.push_back(new ListNode(test[i]));
}
for (int i = 0; i < hash_node_vec.size(); i++){
insert(hash_table, hash_node_vec[i], TABLE_LEN);
}
printf("Hash table:\n");
for (int i = 0; i < TABLE_LEN; i++){
printf("[%d]:", i);
ListNode *head = hash_table[i];
while(head){
printf("->%d", head->val);
head = head->next;
}
printf("\n");
}
printf("\n");
printf("Test search:\n");
for (int i = 0; i < 10; i++){
if (search(hash_table, i, TABLE_LEN)){
printf("%d is in the hash table.\n");
}
else{
printf("%d is not in the hash table.\n");
}
}
return 0;
}
最长回文串
LeetCode 409.Longest Palindrome
已知一个只包括大小写字符的字符串,求用该字符串中的字符可以生成的最长回文字符串长度。
例如s="abccccddaa",可生成的最长回文字符串长度为9,如dccaaaccd、adccbccda、acdcacdca等,都是正确的。
总体思路
细节设计
代码实现
#include <stdio.h>
#include <string>
class Solution {
public:
int longestPalindrome(std::string s) {
int char_map[128] = {0};
int max_length = 0;
int flag = 0;
for (int i = 0; i < s.length(); i++){
char_map[s[i]]++;
}
for (int i = 0; i < 128; i++){
if (char_map[i] % 2 == 0){
max_length += char_map[i];
}
else{
max_length += char_map[i] - 1;
flag = 1;
}
}
return max_length + flag;
}
};
int main(){
std::string s = "abccccddaa";
Solution solve;
printf("%d\n", solve.longestPalindrome(s));
return 0;
}
词语模式
LeetCode 290.Word Pattern
已知字符串pattern与字符串str,确认str是否与pattern匹配。str与pattern匹配代表字符串str中的单词与pattern中的字符一一对应。(其中pattern中只包含小写字符,str中的单词只包含小写字符,使用空格分隔)
总体思路
细节设计
代码实现
#include <stdio.h>
#include <string>
#include <map>
class Solution {
public:
bool wordPattern(std::string pattern, std::string str) {
std::map<std::string, char> word_map;
char used[128] = {0};
std::string word;
int pos = 0;
str.push_back(' ');
for (int i = 0; i < str.length(); i++){
if (str[i] == ' '){
if (pos == pattern.length()){
return 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;
}
};
int main(){
std::string pattern = "abba";
std::string str = "dog cat cat dog";
Solution solve;
printf("%d\n", solve.wordPattern(pattern, str));
return 0;
}
同字符词语分组
LeetCode 49.Group Anagrams
已知一组字符串,将所有anagram(由颠倒字母顺序而构成的字)放到一起输出。
Solve1
总体思路
细节设计
代码实现
#include <stdio.h>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
class Solution {
public:
std::vector<std::vector<std::string> > groupAnagrams(
std::vector<std::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;
}
};
int main(){
std::vector<std::string> strs;
strs.push_back("eat");
strs.push_back("tea");
strs.push_back("tan");
strs.push_back("ate");
strs.push_back("nat");
strs.push_back("bat");
Solution solve;
std::vector<std::vector<std::string> > result
= solve.groupAnagrams(strs);
for (int i = 0; i < result.size(); i++){
for (int j = 0; j < result[i].size(); j++){
printf("[%s]", result[i][j].c_str());
}
printf("\n");
}
return 0;
}
Solve2
总体思路
代码实现
#include <stdio.h>
#include <vector>
#include <string>
#include <map>
void change_to_vector(std::string &str, std::vector<int> &vec){
for (int i = 0; i < 26; i++){
vec.push_back(0);
}
for (int i = 0; i < str.length(); i++){
vec[str[i]-'a']++;
}
}
class Solution {
public:
std::vector<std::vector<std::string> > groupAnagrams(
std::vector<std::string>& strs) {
std::map<std::vector<int>, std::vector<std::string> > anagram;
std::vector<std::vector<std::string> > result;
for (int i = 0; i < strs.size(); i++){
std::vector<int> vec;
change_to_vector(strs[i], vec);
if (anagram.find(vec) == anagram.end()){
std::vector<std::string> item;
anagram[vec] = item;
}
anagram[vec].push_back(strs[i]);
}
std::map<std::vector<int>,
std::vector<std::string> > ::iterator it;
for (it = anagram.begin(); it != anagram.end(); it++){
result.push_back((*it).second);
}
return result;
}
};
int main(){
std::vector<std::string> strs;
strs.push_back("eat");
strs.push_back("tea");
strs.push_back("tan");
strs.push_back("ate");
strs.push_back("nat");
strs.push_back("bat");
Solution solve;
std::vector<std::vector<std::string> > result = solve.groupAnagrams(strs);
for (int i = 0; i < result.size(); i++){
for (int j = 0; j < result[i].size(); j++){
printf("[%s]", result[i][j].c_str());
}
printf("\n");
}
return 0;
}
无重复字符的最长字串
LeetCode 3.Longest Substring Without Repeating Characters
已知一个字符串,求用该字符串的无重复字符的最长子串的长度。
总体思路
细节设计
代码实现
#include <stdio.h>
#include <string>
class Solution {
public:
int lengthOfLongestSubstring(std::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[begin]]--;
begin++;
}
word = "";
for (int j = begin; j <= i; j++){
word += s[j];
}
}
}
return result;
}
};
int main(){
std::string s = "abcbadab";
Solution solve;
printf("%d\n", solve.lengthOfLongestSubstring(s));
return 0;
}
重复的DNA序列
LeetCode 187.Repeated DNA Sequences
将DNA序列看作是只包含['A','C','G','T']4个字符的字符串,给一个DNA字符串,找到所有长度为10的且出现超过1次的字串。
Solve1
总体思路
代码实现
#include <stdio.h>
#include <vector>
#include <string>
#include <map>
class Solution {
public:
std::vector<std::string> findRepeatedDnaSequences(std::string s) {
std::map<std::string, int> word_map;
std::vector<std::string> result;
for (int i = 0; i < s.length(); i++){
std::string word = s.substr(i, 10);
if (word_map.find(word) != word_map.end()){
word_map[word] += 1;
}
else{
word_map[word] = 1;
}
}
std::map<std::string, int> ::iterator it;
for (it = word_map.begin(); it != word_map.end(); it++){
if (it->second > 1){
result.push_back(it->first);
}
}
return result;
}
};
int main(){
std::string s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT";
Solution solve;
std::vector<std::string> result = solve.findRepeatedDnaSequences(s);
for (int i = 0; i < result.size(); i++){
printf("%s\n", result[i].c_str());
}
return 0;
}
Solve2
总体思路
细节设计
代码实现
#include <stdio.h>
#include <vector>
#include <string>
int g_hash_map[1048576] = {0};
std::string change_int_to_DNA(int DNA){
static const char DNA_CHAR[] = {'A', 'C', 'G', 'T'};
std::string str;
for (int i = 0; i < 10; i++){
str += DNA_CHAR[DNA & 3];
DNA = DNA >> 2;
}
return str;
}
class Solution {
public:
std::vector<std::string> findRepeatedDnaSequences(std::string s) {
std::vector<std::string> result;
if (s.length() < 10){
return result;
}
for (int i = 0; i < 1048576; i++){
g_hash_map[i] = 0;
}
int char_map[128] = {0};
char_map['A'] = 0;
char_map['C'] = 1;
char_map['G'] = 2;
char_map['T'] = 3;
int key = 0;
for (int i = 9; i >= 0; i--){
key = (key << 2) + char_map[s[i]];
}
g_hash_map[key] = 1;
for (int i = 10; i < s.length(); i++){
key = key >> 2;
key = key | (char_map[s[i]] << 18);
g_hash_map[key]++;
}
for (int i = 0; i < 1048576; i++){
if (g_hash_map[i] > 1){
result.push_back(change_int_to_DNA(i));
}
}
return result;
}
};
int main(){
std::string s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT";
Solution solve;
std::vector<std::string> result = solve.findRepeatedDnaSequences(s);
for (int i = 0; i < result.size(); i++){
printf("%s\n", result[i].c_str());
}
return 0;
}
最小窗口字串
LeetCode 3.Longest Substring Without Repeating Characters
已知字符串S与字符串T,求在S中的最小窗口(区间),使得这个区间中包含了字符串T中的所有字符。
总体思路
细节设计
代码实现
#include <stdio.h>
#include <string>
class Solution {
public:
int lengthOfLongestSubstring(std::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[begin]]--;
begin++;
}
word = "";
for (int j = begin; j <= i; j++){
word += s[j];
}
}
}
return result;
}
};
int main(){
std::string s = "abcbadab";
Solution solve;
printf("%d\n", solve.lengthOfLongestSubstring(s));
return 0;
}