Leetcode学习之哈希表与字符串 (1)

开宗明义:本系列基于小象学院林沐老师课程《面试算法 LeetCode 刷题班》,刷题小白,旨在理解和交流,重在记录,望各位大牛指点!


Leetcode学习之哈希表与字符串 (1)



1、哈希表基础知识

哈希表:(Hash table)根据关键字值(key)直接进行访问的数据结构,它通过把关键字值映射到表中一个位置(数组下标)来直接访问,以加快查找关键字值的速度。这个映射函数叫做哈希函数,存放记录的数组叫做哈希表。给定表M,存在函数 f ( k e y ) f(key) f(key),对任意的关键字key,代入函数后若能得到包含该关键字的表中位置,称表M为哈希表,函数 f ( k e y ) f(key) f(key)为哈希函数。
在这里插入图片描述


1、哈希-字符串
测试代码:

#include <stdio.h>
#include <string>  //ASC2码,从0-127,故使用下标做映射,最大范围为128
using namespace std;

int main() {
	int char_map[128] = { 0 };
	string str = "abcdefgaaxy";
	//统计字符串中,各个字符的数量
	//char_map['a']++ 表示 char_map[97]++
	for (int i = 0; i < str.length(); i++) {
		char_map[str[i]]++;
	}

	for (int i = 0; i < 128; i++) {
		if (char_map[i] > 0) {
			printf("[%c][%d]:%d\n", i, i, char_map[i]);
		}
	}
	system("pause");
	return 0;
}

效果图
在这里插入图片描述


2、哈希表排序整数
测试代码:

#include <stdio.h>
#include <string>  //哈希表排序,使用数组的下标对正整数排序
using namespace std;  // 哈希表的长度,需要超过最大待排序数组

int main() {
	int random[10] = { 999,1,444,7,20,9,1,3,7,7 };
	int hash_map[1000] = { 0 };

	for (int i = 0; i < 10; i++) {
		hash_map[random[i]]++;
	}

	for (int i = 0; i < 1000; i++) {
		for (int j = 0; j < hash_map[i]; j++) {
			printf("%d\n", i);
		}
	}
	system("pause");
	return 0;
}

效果图
在这里插入图片描述


3、任何元素的映射
在这里插入图片描述
测试代码:

#include <stdio.h>
#include <string>  //哈希表排序,使用数组的下标对正整数排序
using namespace std;  // 哈希表的长度,需要超过最大待排序数组

//直接对整数取余表长再返回
int int_func(int key, int table_len) {
	return key%table_len;
}

//将字符串的字符的ASC2码相加得到整数再取余表长
int string_func(string key, int table_len) {
	int sum;
	for (int i = 0; i < key.length(); i++) {
		sum = sum + key[i];
	}
	return sum % table_len;
}

int main() {
	const int TABLE_LEN = 10;
	int hash_map[TABLE_LEN] = { 0 };
	hash_map[int_func(99999995, TABLE_LEN)]++;
	hash_map[int_func(5, TABLE_LEN)]++;
	hash_map[string_func("abc", TABLE_LEN)]++;
	hash_map[string_func("bac", TABLE_LEN)]++;

	for (int i = 0; i < TABLE_LEN; i++) {
		printf("hash_map[%d] = %d \n", i, hash_map[i]);
	}
	system("pause");
	return 0;
}

上段代码的出错原因为:不同的整数或者字符串,由于哈希函数的选择,被映射到了同一个下标处,产生了冲突!
=>拉链法,来构造哈希表!

在这里插入图片描述
测试代码:

#include <stdio.h>
#include <vector>
using namespace std;

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 };
	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]));
	}

	//将同一个加入hash_table中
	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)) { //查找这个key里面是否有这个
			printf("%d is in the hash table.\n",i);
		}
		else{
			printf("%d is not in the hash table.\n",i);
		}
	}
	system("pause");
	return 0;
}

效果图
在这里插入图片描述


4、哈希map与STL map
测试代码:

#include <stdio.h>
#include <map>
#include <string>
using namespace std;

struct ListNode {
	string key; 
	int val;
	ListNode *next;
	ListNode(int x):val(x),next(NULL){}
};

int main() {
	map<string, int> hash_map;	//将字符串key映射为整数val
	string str1 = "abc";
	string str2 = "aaa";
	string str3 = "xxxxx";
	hash_map[str1] = 1;
	hash_map[str2] = 2;
	hash_map[str3] = 100;
	if (hash_map.find(str1) != hash_map.end()) {
		printf("%s is in hash_map, value is %d\n", str1.c_str(), hash_map[str1]);
	}

	map<string, int>::iterator it;   //这边使用迭代器 注意用法 很常用
	for (it = hash_map.begin(); it != hash_map.end(); it++) {
		printf("hash_map[%s] = %d \n", it->first.c_str(), it->second);
	}
	system("pause");
	return 0;
}

效果图
在这里插入图片描述


2、最长回文串(字符哈希)LeetCode 409.

题目来源 L e e t C o d e   409.   L o n g e s t   P a l i n d r o m e LeetCode \ 409. \ Longest \ Palindrome LeetCode 409. Longest Palindrome
回文字符串:除了中心字符之外,其余字符只要头部出现,尾部就要对应出现
描述已知一个只包括大小写字符的字符串,求用该字符串中的字符可以生成的最长回文字符串长度
在这里插入图片描述
分析根据回文字符串的特性,我们需要探讨字符数量为奇数和偶数的两种情况
在这里插入图片描述
在这里插入图片描述
测试代码:

#include <stdio.h>
#include <map>
#include <string>
using namespace std;

struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x):val(x),next(NULL){}
};

class Solution {
public:
	int longestPalidrome(string s) {
		int char_map[128] = { 0 }; //字符哈希
		int max_length = 0;		//回文串偶数部分的最大长度
		int flag = 0;	//是否有中心点
		//key->value++
		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 = max_length + char_map[i];
			}
			else{	//	如果某字符为奇数个,则丢弃一个,其余的都使用在回文串里面
				max_length = max_length + char_map[i] - 1;
				flag = 1;
			}	//此时标记回文串里面有中心点
		}
		return max_length + flag;
	}
};	//最终结果是偶数部分的最大长度+中心点字符

int main() {
	string s = "abccccddaa";
	Solution solve;
	printf("%d\n", solve.longestPalidrome(s));
	system("pause");
	return 0;
}

效果图
在这里插入图片描述


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值