基础知识
单链表解决冲突:
单链表结构:
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;
}
leetcode 题目:
409. Longest Palindrome
题意:
给一个字符串,重新组合字符串,求能组合出的最长回文数。
解题思路:
用字符哈希存储数据:
1、偶数个:全部使用。
2、奇数个:丢掉一个再全部使用。
3、有剩余的话随便选一个。
a对应97 z对应122
A对应65 Z对应90
会自动转换
代码:
class Solution {
public:
int longestPalindrome(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;
}
};
290. Word Pattern
题意:
一个word对应一个字母,看是否能对应上。
解题思路:
用2个数据结构:
1、用word_map 一个map储存词到字母的字典。
2、用char的哈希表存储每个字母是否已经被使用。
判断长度是否相等。
代码:
class Solution {
public:
bool wordPattern(string pattern, string str) {
map<string, char> word_map;
char used[128] = {0};
int pos = 0;
str.push_back(' '); //保持一致性,每个词后面有一个空格
string word;
for (int i = 0; i < str.length(); i++){
if (str[i] == ' '){
if (pos == pattern.length()){
return false; //证明word的数量比字母数量多
}
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;
}
};
49. Group Anagrams
题意:
把由颠倒字母构成的字符串放在同一个数组里,一起输出。
解题思路:
构造哈希表的做法:
1、先对每个单词的字符串进行排序,将排序好的字符串作为key。
(每个单词复杂度:nlogn)适用于短单词
2、以每个单词出现的次数作为hash的key。
(每个单词复杂度:n)适用于长单词
代码:
//制作hash的key
void change_to_vector(string &str, 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:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> result;
map<vector<int>, vector<string>> anagram;
for (int i = 0; i < strs.size(); i++){
vector<int> vec;
change_to_vector(strs[i], vec);
if (anagram.find(vec) == anagram.end()){
vector<string> item;
anagram[vec] = item;
}
anagram[vec].push_back(strs[i]);
}
map<vector<int>, vector<string>> ::iterator it;
for (it = anagram.begin(); it != anagram.end(); it++){
result.push_back((*it).second);
}
return result;
}
};
3. Longest Substring Without Repeating Characters
题意:
寻找字符串中无重复字符的最长子字符串。
解题思路:
用双指针搜索字符串的方法进行扫描。
数据结构:
1、记录字符数量的字符哈希 char_map
2、记录当前最长子串的word
3、begin end两个字符指针
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int begin = 0;
int result = 0;
string word = "";
int char_map[128] = {0}; //看作key为int,值为int的map
// 如果是char char_map[128] = {0};则是key为int,值为char的map
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;
}
};
187. Repeated DNA Sequences
题意:
将DNA序列看作是只包含ACGT的序列字符串,给一个DNA字符串,找出所有长度为10且出现次数超过1次的子串。
解题思路:
1、简单解决:用字符串哈希表,遍历字符串,找出hash对应的int大于1的
2、复杂方法(一种解题思想):每个位有4种可能,一共10位,可以将子串映射到4**1的整数空间中。
代码:
方法一:
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 substring = s.substr(i, 10); //取子串的方法
if (word_map.find(substring) == word_map.end()){
word_map[substring] = 1;
}
else{
word_map[substring] += 1;
}
}
map<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 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;
}
};
76. Minimum Window Substring
题意:
有字符串S和T,求S中的最小字符串,该字符串包含T中所有的字符。
解题思路:
代码:
class Solution {
private:
bool is_window_ok(int map_s[], int map_t[], std::vector<int> &vec_t){
for (int i = 0; i < vec_t.size(); i++){
if (map_s[vec_t[i]] < map_t[vec_t[i]]){
return false;
}
}
return true;
}
public:
std::string minWindow(std::string s, std::string t) {
const int MAX_ARRAY_LEN = 128;
int map_t[MAX_ARRAY_LEN] = {0};
int map_s[MAX_ARRAY_LEN] = {0};
std::vector<int> vec_t;
for (int i = 0; i < t.length(); i++){
map_t[t[i]]++;
}
for (int i = 0; i < MAX_ARRAY_LEN; i++){
if (map_t[i] > 0){
vec_t.push_back(i);
}
}
int window_begin = 0;
std::string result;
for (int i = 0; i < s.length(); i++){
map_s[s[i]]++;
while(window_begin < i){
char begin_ch = s[window_begin];
if (map_t[begin_ch] == 0){
window_begin++;
}
else if (map_s[begin_ch] > map_t[begin_ch]){
map_s[begin_ch]--;
window_begin++;
}
else{
break;
}
}
if (is_window_ok(map_s, map_t, vec_t)){
int new_window_len = i - window_begin + 1;
if (result == "" || result.length() > new_window_len){
result = s.substr(window_begin, new_window_len);
}
}
}
return result;
}
};