哈希的妙用

假设须要推断多个字符是不是在某个字符串里面出现过或者统计多个字符在某个字符串中出现的次数,我们能够考虑基于数组创建一个简单的hash表,这样能够用非常小的空间消耗来换取时间效率的提升。

题目1:从第一个字符串中删除第二个字符串中出现的全部字符

思路:准备一个hash数组。遍历第二个串,并以每一个字符所相应的asc码作为下标,值为是否出现,1代表出现。然后遍历第一个串。每遍历一个字符,就查询hash表(O(1)),若值为1。那么删除该字符。

/*
从第一个字符串中删除第二个字符串中出现的全部字符
by Rowandjj
2014/8/18
*/
#include<iostream>
#include<string.h>
using namespace std;
#define MAX_SIZE 256
//在串1中删除全部出如今串2中的字符
void DeleteChar(char *str1,char *str2)
{
	if(str1 == NULL || str2 == NULL)
	{
		return;
	}
	char table[MAX_SIZE];//准备一个哈希数组
	int i,j;
	for(i = 0; i < MAX_SIZE; i++)//初始化哈希数组
	{
		table[i] = 0;
	}
	for(i = 0; *(str2+i)!='\0';i++)//以每一个字符的asc码相应的数字作为数组下标。值为1代表出现过
	{
		table[*(str2+i)] = 1;
	}
	for(i = 0; *(str1+i) != '\0'; i++)//遍历串1。删除在串2中出现的每一个字符
	{
		if(table[*(str1+i)] == 1)
		{
			for(j = i+1;*(str1+j) != '\0';j++)//这里须要移动字符
			{//假设同意,能够使用空间换时间
				*(str1+j-1) = *(str1+j);
			}
			*(str1+j-1) = '\0';
		}
	}
}
int main()
{
	char str1[] = "We are students.";
	char *str2 = "aeiou";
	DeleteChar(str1,str2);
	cout<<str1<<endl;
	return 0;
}

题目2:推断两个单词是否是变位词。变位词指的是两个单词字母同样,仅仅是顺序不同。

思路:准备一个hash数组记录每一个字母出现的次数,对第一个单词,为hash表相应表项增1,对第二个单词则是减1,这样假设终于hash表每一个值都是0,则说明是变位词。

代码:

/*
推断两个单词是否为变位词
by Rowandjj
2014/8/18
*/
#include<iostream>
#include<string.h>
using namespace std;
#define MAX_WORD_SIZE 256
bool isAnagram(char *str1,char *str2)
{
	if(str1 == NULL || str2 == NULL)
	{
		return false;
	}
	int len = strlen(str1);
	if(len != strlen(str2))
	{
		return false;
	}
	int i;
	int table[MAX_WORD_SIZE];//准备一个hash数组
	for(i = 0; i < MAX_WORD_SIZE; i++)
	{
		table[i] = 0;
	}
	for(i = 0; i < len; i++)//为hash表相应每一个字母出现次数增1
	{
		table[*(str1+i)]++;
	}
	for(i = 0; i < len; i++)//为hash表相应每一个字母出现次数减1
	{
		table[*(str2+i)]--;
	}
	for(i = 0; i < MAX_WORD_SIZE; i++)//假设hash每一个值都为0,那么就是变位词
	{
		if(table[i] != 0)
		{
			return false;
		}
	}
	return true;
}
int main()
{
	char *str1 = "evil";
	char *str2 = "live";
	if(isAnagram(str1,str2))
	{
		cout<<"YES"<<endl;
	}else
	{
		cout<<"NO"<<endl;
	}
	return 0;
}

题目3:删除字符串中全部反复出现的字符。

思路:准备一个hash表,下标代表字符的asc码。值代表是否反复,这样我们仅仅需0(1)的时间就可以推断一个字符是否在前面出现过。

代码:

/*
删除字符串中全部反复出现的字符
by Rowandjj
2014/8/18
*/
#include<iostream>
#include<string.h>
using namespace std;
#define MAX 256
//去掉反复字符
void deleteRepeatChar(char *str)
{
	if(str == NULL)
	{
		return;
	}
	int table[MAX];
	int i;
	for(i = 0; i < MAX; i++)//初始化哈希表
	{
		table[i] = 0;
	}
	int len = strlen(str);
	char *temp = (char*)malloc(sizeof(char)*len);//存放不带反复字符的新串。避免移动原串
	if(!temp)
	{
		exit(-1);
	}
	int j = 0;
	for(i = 0; i < len; i++)
	{
		if(table[*(str+i)] == 1)//该字符反复
		{
			continue;
		}else//该字符不反复
		{
			table[*(str+i)] = 1;
			temp[j++] = *(str+i);//拷贝到新串
		}
	}
	for(i = 0; i < j; i++)//将新串中的字符拷贝到原始串中
	{
		str[i] = temp[i];
	}
	*(str+i) = '\0';//别忘了还要复制结束符
	free(temp);
}
int main()
{
	char str[] = "google";
	deleteRepeatChar(str);
	cout<<str<<endl;
	return 0;
}
时间: 2024-10-25 11:24:42

哈希的妙用的相关文章

证明与计算(5): 从加密哈希函数到一致性哈希

目录: ** 0x01 [哈希函数] vs [加密哈希函数] ** 0x02 [哈希碰撞] vs [生日问题] ** 0x03 [哈希表] vs [分布式哈希表] ** 0x04 [欧式距离] vs [三角不等式] ** 0x05 [异或距离] vs [前缀路由表] 0x01 [哈希函数] vs [加密哈希函数] 在哈希表计算索引的时候,我们需要一个哈希函数,通过hash(key)来计算key在哈希表里的index.这个地方的哈希函数只要尽量满足均匀分布,周期尽量大,计算速度又足够快等即可.而在

c# 扩展方法奇思妙用基础篇五:Dictionary&lt;TKey, TValue&gt; 扩展

Dictionary<TKey, TValue>类是常用的一个基础类,但用起来有时确不是很方便.本文逐一讨论,并使用扩展方法解决. 向字典中添加键和值 添加键和值使用 Add 方法,但很多时候,我们是不敢轻易添加的,因为 Dictionary<TKey, TValue>不允许重复,尝试添加重复的键时 Add 方法引发 ArgumentException. 大多时候,我们都会写成以下的样子: var dict = new Dictionary<int, string>()

NYOJ 2356: 哈希计划【模拟】

题目描述 众所周知,LLM的算法之所以菜,就是因为成天打游戏,最近LLM突然想玩<金庸群侠传X>,结果进去后各种被虐,LLM就开始研究这个游戏的代码,顺便还学会了一点点点点lua语言,然后就开始了伟大的改游戏代码之旅,然后LLM发现自己too young了,这个游戏把所有的文本都进行了哈希,如果自己改了代码或者剧情文本的话它哈希出来的值就会和原来的哈希值不一样......然后游戏就会打不开.....,现在LLM发现了文本的哈希函数,要求你写个程序,功能为: 输入一段字符串,输出一个哈希值 为了

7.哈希

哈希(Hash)又称散列,它是一个很常见的算法.在Java的HashMap数据结构中主要就利用了哈希.哈希算法包括了哈希函数和哈希表两部分.我们数组的特性可以知道,可以通过下标快速(O(1))的定位元素,同理在哈希表中我们可以通过键(哈希值)快速的定位某个值,这个哈希值的计算就是通过哈希函数(hash(key) = address )计算得出的.通过哈希值即能定位元素[address] = value,原理同数组类似. 最好的哈希函数当然是每个key值都能计算出唯一的哈希值,但往往可能存在不同的

哈希表

哈希表支持的一种最有效的检索方法:散列. 由于计算哈希值和在数组中进行索引都只消耗固定时间,因此哈希表的最大亮点在于他是一种运行时间在常量级的检索方法. 哈希表主要有两种: 1.链式哈希表:将数据存储在桶中的哈希表,每个桶里面都是一个链表,且链表的容量随着冲突的增大而增大.(换句话说就是如果有冲突,会在桶中的链表加上一个存储的值) 2.开地址哈希表:将数据存在表本身,而不是在桶中,他通过各种探查方法来避免冲突. 解决冲突: 不管在以上那种哈希表中,我们的目标是尽可能均匀的分配表中的元素.所以我们

Aizu 2784 Similarity of Subtrees(树哈希)

Similarity of Subtrees Define the depth of a node in a rooted tree by applying the following rules recursively: The depth of a root node is 0. The depths of child nodes whose parents are with depth d are d+1 . Let S(T,d) be the number of nodes of T w

8. 蛤蟆的数据结构进阶八哈希表相关概念

8. 蛤蟆的数据结构进阶八哈希表相关概念 本篇名言:"作家当然必须挣钱才能生活,写作,但是他决不应该为了挣钱而生活,写作.--马克思" 前些笔记我们学习了二叉树相关.现在我们来看下哈希表.这篇先来看下哈希表的相关概念 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47347273 1.  哈希表的概念 哈希表(HashTable)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构.它通过把关键

哈希(4) - 求两个链表的交集(intersection)以及并集(union)

给定两个链表,求它们的交集以及并集.用于输出的list中的元素顺序可不予考虑. 例子: 输入下面两个链表: list1: 10->15->4->20 list2: 8->4->2->10 输出链表: 交集list: 4->10 并集list: 2->8->20->4->15->10 方法1 (简单方法) 可以参考链表系列中的"链表操作 - 求两个链表的交集(intersection)以及并集(union)" 方法2

哈希(5) - 检测数组A[]中是否存在元素对其和为x

给定一个包括n个数值的数组A[]以及另一个数字x,判断数组中是否存在一对元素,它们的和等于x. 方法1 (使用排序) 算法: hasArrayTwoCandidates (A[], arrSize, sum) 1) 对数组进行递增排序 2) 初始化已排序数组中的两个索引值 (a) 将最左侧的数组位置0做为第一个索引left = 0 (b) 将最右侧的数组位置做为第二个索引right = arrSize-1 3) Loop while left < right. (a) if (A[left] +