微软面试百题017——哈希查找/优先队列

1.题目描述:

在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。

2.算法讲解:

本题中,我们需要一种数据结构可以让我们通过读取字符从而查找到对应的出现次数,并且我们要尽可能的提高查找的速度

所以我们就会考虑到一种数据结构——哈希表,详情请点击点击打开链接

我们都知道,通过哈希表,我们可以将存取的速度提高到O(1)的复杂度

并且,题目中,我们是将字符映射到对应的数据上的,所以说我们的哈希函数也是非常的好设定,我们直接将字符作为的关键字通过哈希函数转化成对应的256以内的ASCII码就很好解决了

但是有的同学可能会说,怎么办,一个字符串中出现相同的字符的话,那不就和哈希要求的减少冲突的要求相违背了吗

在这里,这个问题很好解决,首先我们需要明确一点,根据题目的特殊性,我们的冲突的解决是不用考虑的,我们有冲突直接计数就好


最后,我们将字符串便利结束之后,我们再次从头开始遍历,找到第一个出现的频度为1的字符就好(哈希对应的键值)


需要的时间复杂度就是O(n)



在这里,本人本来想要通过优先队列的方法看可不可以达到和哈希一样的额优化效果 

3.代码:

#include"iostream"
#include"cstdio"
#include"cstring"
#include"cstdlib"
#define N 260

using namespace std;

int hash[N];
char data[10000];

void hashfunction(char p)
{
	hash[(int)p]++;
}

int main()
{
	memset(hash,0,sizeof(hash));
	memset(data,0,sizeof(data));
	scanf("%s",data);
	for(int i=0;i<strlen(data);i++) hashfunction(data[i]);
	for(int i=0;i<strlen(data);i++) 
	{
		if(hash[(int)data[i]]==1) 
		{
			cout<<data[i]<<endl;
			break;
		}
	}
	return 0;
}


优先队列的方法:

我们的count数组用来记录我们的对应的ASCII码对应的出现次数,我们用堆来维护标号,pos来查找对应的标号在堆中的位置

实际的算法的复杂度是O(N*lgN)但是实际上我们的复杂度要远远比这个小,没有哈希表的方法优秀,但是总归是一种思路

#include"iostream"
#include"cstdio"
#include"cstdlib"
#include"cstring"
#define N 260

using namespace std;

int count[N];
int heap[N];  //记录标号 
int pos[N];   //记录位置 
char data[10000];

void swap(int x,int y)
{
	int t=heap[x];
	heap[x]=heap[y];
	heap[y]=t;
	
	t=pos[heap[x]];
	pos[heap[x]]=pos[heap[y]];
	pos[heap[y]]=t;
}

void siftup(int i)
{
	while(i!=1)
	{
		if(count[heap[i/2]]!=1||heap[i]<heap[i/2]) 
		{
			swap(i,i/2);
			i=i/2;
		}
		else break;
	}
}

void siftdown(int i)
{
	int t=i;
	while(i*2<N)
	{
		if(count[heap[i*2]==1]) t=i*2;
		if(i*2+1<N&&count[heap[i*2+1]]==1)
		{
			if(t==i) t=i*2+1;
			else if(heap[i*2+1]<heap[i*2]) t=i*2+1; 
		}
		if(t!=i)
		{
			swap(i,t);
			i=t;
		} 
		else break;
	}
}

int main()
{
	for(int i=1;i<N;i++) heap[i]=pos[i]=i;
	memset(count,0,sizeof(count));
	memset(data,0,sizeof(data));
	scanf("%s",data+1);
	for(int i=1;i<strlen(data+1);i++)
	{
		count[(int)data[i]]++;
		if(count[(int)data[i]]==1) siftup(pos[(int)data[i]]);
		else siftdown(pos[(int)data[i]]);
	}
	printf("%c\n",heap[1]);
	return 0;
} 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值