每日练习3-找出字符串第一个只出现一次的字符

题目:

        找出字符串第一个只出现一次的字符

解决思路:

        我们可以通过遍历字符串,并统计相同元素的出现次数,取最小的一个。但是这样我们的时间复杂度为O(n^2)。

(1)本文介绍“以空间换时间”的思想实现O(n)的算法;

(2)创建一个哈希表,以每个字符ASCII码值为下标,相应内容为该字符的出现次数的哈希表,同时,一个字符有8个bit位,所以ASCII码可能是0-256,所以我们要创建的哈希表长度应为256;

(3)遍历字符串,将每个出现的字符次数填入到哈希表中;

(4)最后,遍历哈希表,找出出现次数最小的字符,将下标即ascii码转换即可输出。

        还有许多要注意的点,我都注释在了代码中。

实现代码:

#include <stdio.h>

#define MAXSIZE 256

int flag = 0;//用来标记函数出错返回的情况

typedef size_t(*HashFunc)(int key);

typedef enum
{
	Empty,//当前位置为空
	Valid,//当前位置有效
}Stat;

typedef struct HashElem
{
	char key;//字符的ASCII码值即下标
	int value;//字符对应的出现次数
	Stat stat;//当前位置的状态,是否有效
	size_t size;//标记该字符第一次出现的在原字符串中的位置
}HashElem;

typedef struct Hash
{
	HashFunc func;//函数指针,用来传入判断存储位置的函数
	HashElem data[MAXSIZE];
}Hash;

size_t HashFuncDefault(int key)//用来计算存储位置的函数
{
	return key % MAXSIZE;
}

void EnterHash(Hash* hash, char arr[], int len, HashFunc func)
{
	int i = 0;
	if (arr == NULL || hash == NULL)
		return;
	hash->func = func;//哈希表初始化
	for (; i < MAXSIZE; ++i)
		hash->data[i].stat = Empty;
	for (i = 0; i < len; ++i)//遍历数组,存入哈希表
	{
		size_t offset = hash->func(arr[i]);
		if (hash->data[offset].stat == Empty)//当当前字符是第一次向哈希表中存
		{
			hash->data[offset].value = 1;
			hash->data[offset].key = arr[i];
			hash->data[offset].stat = Valid;
			hash->data[offset].size = i;
		}
		else//当前字符已在哈希表中了
			hash->data[offset].value += 1;
	}
}

char FindOneTimeNum(Hash* hash)
{
	int ret = 0;//用来标记第一个不为空的元素
	size_t i = 0;
	int num = -1;//用来比较存放最先在字符串中出现的字符,因为哈希表中存是按照ascii码而不是先后出现顺序
	if (hash == NULL)
	{
		flag = -1;
		return 'X';
	}
	for (i = 0; i < MAXSIZE; ++i)
	{
		if (hash->data[i].stat == Valid && hash->data[i].value == 1)//当前字符仅在字符串中出现了一次
		{
			if (ret == 0)//num还未记录的有仅出现一次的字符
			{
				num = i;
				ret = 1;
			}
			else
			{
				if (hash->data[num].size > hash->data[i].size)//当前字符比num记录的字符更先出现在字符串
					num = i;
			}
		}
	}
	if (num == -1)
		return 'X';
	return hash->data[num].key;
}

int main()
{
	char arr[] = "acuiasoasb";
	int size = sizeof(arr) / sizeof(arr[0]) - 1;
	Hash hash;
	char ret;
	EnterHash(&hash, arr, size, HashFuncDefault);
	ret = FindOneTimeNum(&hash);
	if (ret == 'X')
	{
		if (flag == -1)
			printf("参数error\n");
		else
			printf("return 0\n");
	}
	else
		printf("expected is c, actual is %c\n", ret);
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lycorisradiata__/article/details/80536030